Enter Your Project for a chance to win an Arduino MKR WAN 1300 Kit with a Compatable Lora Gateway or an MKR 1400 GSM with a Shield Combo + a $100 shopping cart! | Project14 Home | |
Monthly Themes | ||
Monthly Theme Poll |
Updated on 8 May 2019
Introduction
Home automation allows us to control household electrical appliances like light, door, fan, and so on. Home automation not only refers to reduce human efforts but also energy efficiency and time saving.
The aim of the project is to implement home automation using Raspberry Pi, Matrix Voice and Snips platform. In this project, Raspberry Pi is connected with Matrix Voice via GPIO pins and all the five lights (such as bedroom, kitchen lights) which we are controlling through voice command are interfaced with expansion GPIO pins of Matrix Voice. We are providing input(voice command) through Matrix voice mic and taking output (response) as light on/off from GPIO of Matrix Voice.
Component Needed
1. Matrix Voice ==> $55
2. Raspberry Pi 3 B+ ==> $35
3. 5V 2.5A Power Supply Adapter ==> $4.78
4. 5V Relay single channel ==> $4
5.16 GB SD card ==> $7.68
Total cost of the project is around $ 106
How to Connect Matrix Voice With RPi 3
The Matrix Voice is a development board for building sound driven behaviors and interfaces. It is an user-friendly tool for simple to complex Internet of Things (IoT) voice app creation. It comes under two versions
1. Matrix Voice version
2. Matrix Voice ESP32 version
Both versions of these boards run the same on a Raspberry Pi, however, the Matrix Voice ESP32 version has the option to run standalone by programming the ESP32 module.
Here I am using Matrix Voice.
Matrix Voice expansion GPIO
DF## pins are equivalent to GPIO## pins.
Raspberry Pi GPIO
Note:- The expansion GPIOs on the Matrix Voice are not connected to the RPi GPIOs. The expansion GPIOs mostly come from the FPGA.
Before installing Matrix OS make sure you have setup Matrix voice. For that you need
- Raspberry Pi 3 Model B
- +5V 2.5A Micro USB Power Supply
- Matrix voice
1. Insert flashed micro SD card into Raspberry Pi
2. Attach Matrix Voice onto Raspberry Pi GPIO pins
3. Power Raspberry Pi with micro USB power supply
Once done next is installing Matrix OS on your personal computer. You can use Windows or macOS or Linux. In this project I am going to use Linux (Ubuntu) to install Matrix OS
Matrix core installation on RPi
Before starting installing make sure you have installed NodeJS and npm
1. To install NodeJS, go to NodeJS and download Linux binaries(x64) of version 10.15.1
and then extract it with
tar -xvf node-v10.15.1-linux-x64.tar.xz
cd node-v10.15.1-linux-x64
sudo cp -R * /usr/local/
sudo apt-get update
sudo apt-get upgrade
and check NodeJS and npm version
node -v
npm -v
1. Add the Matrix repository and key.
curl https://apt.matrix.one/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.matrix.one/raspbian $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/matrixlabs.list
Matrix repository for Matrix HAL
curl https://apt.matrix.one/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.matrix.one/raspbian $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/matrixlabs.list
Update your repository and packages.
sudo apt-get update
sudo apt-get upgrade
2. Install the the Matrix Core packages.
sudo apt-get install matrixio-malos
sudo reboot
Install the the MATRIX HAL packages.
sudo apt-get install matrixio-creator-init libmatrixio-creator-hal libmatrixio-creator-hal-dev
Reboot your device.
sudo reboot
3. To install ZeroMQ
echo "deb http://download.opensuse.org/repositories/network:/messaging:/zeromq:/release-stable/Debian_9.0/ ./" | sudo tee /etc/apt/sources.list.d/zeromq.list
wget https://download.opensuse.org/repositories/network:/messaging:/zeromq:/release-stable/Debian_9.0/Release.key -O- | sudo apt-key add
4. JavaScript setup
Create a node project folder in the home directory of RPi
cd ~/ mkdir js-matrix-core-app (whatever name you want)
cd js-matrix-core-app
npm init
5. Installing npm Packages for ZMQ and Protocol Buffers
To install the ZMQ and MATRIX Protocol Buffers npm packages. Make sure you are in directory which you created above (name you give). Here I gave it js-matrix-core-app. This allows you to interact with Matrix Core through Node.js.
npm install zeromq --save
npm install matrix-protos --save
To use PWM for external LEDs and servo motor I am using Matrix lite library.
npm install @matrix-io/matrix-lite --save
Now you are done with Matrix core and Matrix HAL.
What is snips
Snips is an AI voice platform for connected devices. It is an end-to-end solution with Speech Recognition and Natural Language Understanding, enabling anyone to add a customizable voice assistant to their product. Snips is the only deep-learning based voice platform that runs fully on-device. It can run without the need for a server or the cloud. It offers Privacy by Design.
How to install the Snips using SAM CLI tool
For this make sure all the steps mentioned above are working
I. Raspberry Pi
1. To Install the matrix Kernel Modules. Run the following commands in your Raspberry Pi's terminal to add the matrix repository & key and update your repository packages.
curl https://apt.matrix.one/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.matrix.one/raspbian $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/matrixlabs.list
sudo apt-get update
sudo apt-get upgrade
sudo reboot
2. To Install the Matrix Kernel modules. Use the command below
sudo apt install matrixio-kernel-modules
This allows the microphones on your matrix device to register as an ALSA microphone on your Raspberry Pi.
sudo reboot
3. Next command will test your microphones by raising your output volume, creating a 5 second long audio recording, and then playing that recording.
Make sure you have select audio jack as output for that
sudo raspi-config
then blue screen appears, go to advanced option then go to audio and select analog jack.
amixer set PCM 100% && arecord recording.wav -f S16_LE -r 16000 -d 5 && aplay recording.wav
If you are able to hear the audio then you are done.
Next we are going to install the SAM tool on desktop
II.Installing the SAM CLI tool on personal computer(Ubuntu)
We are using the SAM CLI tool to create, manage and deploy our Snips assistants, to configure hardware, to view the logs of assistants on the Raspberry Pi, as well as to run your application locally for quick prototyping.
1. Install SAM into your computer with the following command.
sudo npm install -g snips-sam
2. Installing Snips.ai through SAM
We are going to install Snips.ai on our Raspberry Pi, Snips will be installed through the SAM CLI tool from our personal computer.
sam devices
This command should log all of the Raspberry Pis on your network with their IP address and host name.
Note:- sam devices not required if you already know your RPi IP address
Connect to your Raspberry Pi using command
sam connect ip address of Pi
eg :- sam connect 192.168.1.68
you'll then be prompted to insert a username and password of RPi.
Once you connected use the sudo init command, from your personal computer, to install Snips onto your Raspberry Pi.
sudo sam init
III. Configuring Snips.ai on Raspberry Pi
Now, edit the snips.toml file for configuring the mics on RPi.
Open terminal and use command to open the snips.toml file
sudo nano /etc/snips.toml
You can use any editor to do changes.
Scroll down to where you see [snips-audio-server] and replace
# mike = "Built-in Microphone"
with the following:
mike = "MATRIXIO SOUND: - (hw:2,0)"
IV.Testing Snips.ai on personal Computer(Ubuntu)
Through your personal computer's terminal, you can use SAM to test the speaker and microphone of your Raspberry Pi.
1. To Test Raspberry Pi's speaker
sam test speaker
2. To Test the microphones on your Matrix device
sam test microphone
If both commands seem to work, you've properly configured Snips.ai on your Raspberry Pi.
If there is some problem use this command
sam setup audio
Then it will ask whether you are using snips kit or not (I choose no)
Then it will ask you to select the microphone. Here I am using Matrix Voice microphone
Then it will ask you to select the speaker. Here I am using RPi audio jack as speaker.
To test Snips.ai is properly working by installing a demo assistant for the weather or not.
sam install demo
After installing as you see snips assistant is running.
Now, test the assistant by saying
"Hey Snips!" "What will the weather be like in Madagascar in two days?"
The response from Snips should be:
"You asked for the weather in Madagascar in two days."
You can test whether all services are running or not using command
sam status
Congratulations we have successfully installed Snips on RPi.
Control lights with Snips.ai
1. Creating a Snips assistant & app
Sign into your Snips.ai and create an assistant. After sign in you page will like this
2. Create a new assistant
3. Give name to an assistant, select language and then create it.Once created you will see page like this
4. Then click on add an app and you will see page like this
5. Select create a new app and give it a name whatever you want and create it
Once created you will see page like this
6. After that open the app, click on edit app.
You will see page like this. As you see I already created intent (lights). You will see no intent on your page.
7. Create a new intent
After creating you will see page like this. My intent name is lights
8. Give training examples (you can give training examples after creating slots also).
9. Then create a new slots and give it name whatever you want. Here I am using four slots
- switch for on and off state
- room for different rooms such as bedroom, bathroom etc
- device for devices such as light, fan etc
- brightness for setting brightness of light in different rooms.
10. Then give slot type name. Here I am building custom slot type.
- For room slot
After that add slot values "bathroom", "bedroom" and "kitchen".
- For switch slot
After that add slot values "on","off","open", and "close".
- For device slot
Give any name whatever you want.
After that add slot values such as "light", "fan", and "door".
- For brightness slot
Give any name whatever you want.
After that add slot values 75, 50, 25, 0
11. Close the app, in order to tell the training example which slot is used, double click on off and on and select slot name(switch).
Double click on room name and select slot name(room).
Double click on light, fan and select slot name(device).
Double click on values(0, 25, 50) and select slot name(brightness).
Then save it and you can test it in window provided right hand side of the page.
Then deploy it
Connect SAM to Raspberry Pi on personal computer
1. From your computer's terminal, sign in through the Sam CLI Tool
sam login
Login using your snips account
2. Connect to your Raspberry Pi. When prompted for a username & password, insert the Raspberry Pi credentials.
sam connect YOUR.PI.IP.HERE
3. Copy the command and paste on your local computer.
After deploying on your Pi you will see like this
Creating Assistant on RPi
Assistant will be used to listen and respond to events from your Snips assistant
1. Go to the directory which we made during JavaScript setup in Matrix core. cd ~/js-matrix-core-app and create 4 new JavaScript files.
touch assistant.js pwm.js everloop.js func.js
2. Install MQTT to listen in on events from Snips.
npm install mqtt --save
3. Open everloop.js using any editorand paste the code given in program. Code is used to control the LEDs on the MATRIX Creator/Voice.
4. Open relay.js using any editor and paste the code given in program. It is used to turn the relay on and off.
5. Open assistant.js using any editor and paste the code given in program. It combines all the code from everloop.js & relay.js to control the everloop and relay switch through voice. It shows you how to listen to lightState intents and read slots.
var snipsUserName = 'ruchir'; // username of snips account
var lightState = 'hermes/intent/'+snipsUserName+':lightState'; // name of intent you give while creating an intent
Once done now it is time to check.Open your personal computer(Ubuntu) terminal and run
sam watch
On the other hand, open RPi terminal and go to the directory
cd js-matrix-core-app/
node assistant.js // run it
Training examples
turn on bathroom light
turn on the kitchen lights
turn off the bedroom lights
turn on all the light
set bathroom light intensity to 25 percent
set kitchen light intensity to 75 percent
set bedroom light intensity to 50 percent
set bedroom light intensity to 0 percent
open the main hall door
close the main hall door
Webpage
I made a page for showing the logs (room, devices, device state, intensity value and date) and gauge showing current intensity value so that I can know which command I used while talking to the snips. Follow the steps giving below for making a webpage.
Note - You can use either Node server or Apache server.
In this project I am using node server because Apache server is slow and it was not able to update data correctly.
Note - If you use code given in this project make sure your all the data is in cd /var/www/html directory or you can change location in the program.
First, to install Apache server using command (Not required)
sudo apt-get install apache2
Apache server is not required if you have node server
or
Node server
Make an empty file name server.js, add program given below and save it.
var http = require('http'); var url = require('url'); var fs = require('fs'); var express=require('express'); var bodyParser=require('body-parser'); var nodemailer=require('nodemailer'); var app = express(); app.post('/formaction',function(req,res){ res.writeHead(301,{'location':'http://127.0.0.1:8080/HA.html'}); res.write('<html><script>function newpage(){window.location.href="localhost:8008/HA.html";}</script><body onload="newpage()"></body></html>'); res.end(); var transporter = nodemailer.createTransport({ service: 'gmail', auth: { user: '', pass: '' } }); console.log('transporter ready'); var mailOptions = { from: '', to: '', subject: 'Sending Email using Node.js', text: Date().toGMTString }; console.log('mail options set'); transporter.sendMail(mailOptions, function(error, info){ if (error) { console.log(error); } else { console.log('Email sent: ' + info.response); } console.log('mail on sending'); }); }).listen(8008); http.createServer(function (req, res) { var q = url.parse(req.url, true); var filename = "." + q.pathname; fs.readFile(filename, function(err, data) { if (err) { res.writeHead(404, {'Content-Type': 'text/html'}); return res.end("404 Not Found"); } res.writeHead(200, {'Content-Type': 'text/html'}); res.write(data); return res.end(); }); }).listen(8080);
To run server use command
node server.js
Next, go to the directory cd /var/www/html and make two folders
1. Make a folder name js using command
mkdir js
cd js // go to the directory
In /var/www/html/js directory make a file name angular.min.js and paste data from the link given below
In same directory make another file name gauge.min.js and paste data from the link given below
2. Make a folder name jsonpage using command
mkdir jsonpage
cd jsonpage
In jsonpage directory make a file name info.js. Make it empty
Note:- Json file will be cleared after 50 voice commands
Login page
For making login page go to the directory cd /var/www/html and make an empty file name index.html. Add program given below
<html> <head> <title>Login Page</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <div align="center"> <p><font color="red"size=5>PLEASE LOGIN TO SEE THE LOGS</font></p> </div> <br> <form name="loginForm" method="POST" action="http://127.0.0.1:8008/formaction"> <table width="20%" bgcolor="0099CC" align="center" > <tr> <td colspan=2><center><font size=4><b>Login Page</b></font></center></td> </tr> <tr> <td>Username:</td> <td><input type="text" size=25 name="userid"></td> </tr> <tr> <td>Password:</td> <td><input type="Password" size=25 name="pwd"></td> </tr> <tr> <td ><input type="Reset"></td> <td><input type="submit" onclick="return check(this.form)" value="Login"></td> </tr> </table> </form> <script language="javascript"> function check(form) { if(form.userid.value == "default" && form.pwd.value == "default") { var date=new Date(); date.setTime(date.getTime()+(15*60*1000));<!-- Time 15--> document.cookie= 'User=default;expires='+date.toGMTString()+';'; return true; } else { alert("Error, Enter valid Username or Password") return false; } } </script> <br><br><br><br> <div align="left"> <p><font color="brown"size=3>Developed by :</font></p> <p><font color="brown"size=5>RUCHIR SHARMA & ADITYA BHARDWAJ </font></p> <p><font color="brown"size=3></font></p> </div> <p><mark><strong>Note: </strong>Supported in Mozilla Firefox & Chromium browser</mark></p> </body> </html>
Main page
For making main page go to the directory cd /var/www/html and make an empty file name HA.html(any). Add program given below
(dummy code)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>GUI View</title> </head> <style> body{ background-size: 100% 100%; align:center; } table{ color: white; border: ridge 3px yellow; } </style> <script src = "./js/angular.min.js"> </script> <script src = './js/gauge.min.js'></script> <script src = 'index.js'></script> <body onload = "checkcookie()" background ='./image/i1.jpeg' ng-app="APP" onmouseover="cellcolor()"> <table border =3 id ='table_id'align="center"> <tr> <td> room & devices </td> <td> device state </td> <td> device intensity </td> <td> Time </td> </tr> <tbody ng-controller="ctrl"> <tr ng-repeat="x in datafile"> <td> {{x.device}} </td> <td> {{x.state}} </td> <td> {{x.intensity}} </td> <td> {{x.time}} </td> </tr> </tbody> </table><br><br> <div style="background-color:yellow;margin-left:350px;margin-right:350px"> <center> <canvas id='gauge'></canvas><br> <div id='demo123'></div> </center> </div> </body> <script> var app= angular.module("APP",[]); app.controller("ctrl", function($scope,$http){ $http.get("./jsonpage/info.json").then(function(response){ $scope.datafile=response.data; }); }); function cellcolor(){ set different color of cell based on text } read(); setTimeout(function(){draw('demo123');},3000); function cookies(){ var name = "User="; var decodedCookie = decodeURIComponent(document.cookie); var ca = decodedCookie.split(';'); for(var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') { c = c.substring(1); } if (c.indexOf(name) == 0) { return c.substring(name.length, c.length); } } } function checkcookie(){ var user=cookies(); if(user==undefined){ window.location.href = 'index.html' } } </script> </html>
For making gauge make a empty file name index.js in cd /var/www/html directory. Program is given below.
function read(){ console.log('js started'); var intensity; var rawfile = new XMLHttpRequest(); rawfile.overrideMimeType("application/json"); rawfile.open("GET", "./jsonpage/info.json", true); rawfile.onreadystatechange = function() { if (rawfile.readyState === 4 && rawfile.status == "200" ) { console.log("ready to read"); var data = JSON.parse(rawfile.responseText); console.log('json parsed'); intensity = data[data.length-1].intensity; console.log('intensity set to ',intensity); console.log('intensity is',intensity); document.getElementById('demo123').innerHTML = intensity; } } rawfile.send(); } function draw(x){ var opts = { angle: -0.1, lineWidth: 0.1, limitMax: 'true', //false title:{ text: 'Intensity' } , strokeColor: 'red', generateGradient: true, pointer: { length: 0.5, //The radius of the inner circle strokeWidth: 0.03, // The rotation offset color: 'red' // Fill color }, staticLabels: { font: "90% sans-serif", // Specifies font labels: [0, 25, 50, 75, 100], // Print labels at these values color: "red", // Optional: Label text color fractionDigits: 2 // Optional: Numerical precision. 0=round off. }, // just experiment with them strokeColor: 'red', // to see which ones work best for you staticZones: [ {strokeStyle: "powderblue", min: 0, max: 25}, // Yellow33 {strokeStyle: "lightskyblue", min: 25, max: 50}, // Green66 {strokeStyle: "royalblue", min: 50, max: 75}, // Yellow {strokeStyle: "blue", min: 75, max: 100}, ], generateGradient: true }; console.log(document.getElementById(x)); // if(document.getElementById(x).firstChild.data == 'zero'){ var inten=0; } if(document.getElementById(x).firstChild.data == 'twenty five'){ var inten=25; } if(document.getElementById(x).firstChild.data == 'fifty'){ var inten=50; } if(document.getElementById(x).firstChild.data == 'seventy five'){ var inten=75; } var gauge_value = inten; console.log(gauge_value); var target = document.getElementById('gauge'); // your canvas element var gauge = new Gauge(target).setOptions(opts); // Donut create sexy gauge! gauge.maxValue = 100; // set max gauge value gauge.animationSpeed = 40; // set animation speed (32 is default value) gauge.set(gauge_value); // set actual value }
Required npm package
For sending mail install node package
npm install nodemailer
Npm package for bidirectional event-based communication
npm install socket.io
Npm package for express
npm install express
If you want to hear the words. You can download this node package.
npm install say
Add these lines in program (example)
const say = require('say') say.speak('Brightness is set to 75');
assistant.js for webpage (dummy code)
var fs=require('fs'); var mqtt = require('mqtt'); var client = mqtt.connect('mqtt://localhost', { port: 1883 }); var func =require('./func.js'); var everloop = require('./everloop.js'); var pwmlight = require('./pwm.js'); var snipsUserName = 'ruchir'; var wakeword = 'hermes/hotword/default/detected'; var sessionEnd = 'hermes/dialogueManager/sessionEnded'; var lightState = 'hermes/intent/'+snipsUserName+':lights'; var nodemailer=require('nodemailer'); ////////////// //ON CONNECT// ////////////// client.on('connect', function() { console.log('Connected to Snips MQTT server\n'); client.subscribe('hermes/hotword/default/detected'); client.subscribe('hermes/dialogueManager/sessionEnded'); client.subscribe(lightState); }); ////////////// //ON MESSAGE// ////////////// client.on('message', function(topic,message) { var message = JSON.parse(message); switch(topic) { // * On Wakeword case wakeword: everloop.startWaiting(); console.log('Wakeword Detected'); break; // * On Light State Change case lightState: // Turn lights On/Off try{ // controlling light using PWM if(message.slots[0].rawValue==='on' || message.slots[0].rawValue==='off'|| message.slots[0].rawValue==='open' || message.slots[0].rawValue==='close'){ var room=message.slots[1].rawValue; // room types slot console.log(room); var state=message.slots[0].rawValue; // state type slot console.log(state); var device=message.slots[2].rawValue;// device type slot console.log(device); switch(room){ // Bathroom light on/off case 'bathroom': if(device ==='light'){ func.roomtype(0,state); console.log("Bathroom light"); } else if(device ==='fan'){ func.roomtype(5,state); console.log("Bathroom fan"); } break; // Bedroom light on/off case 'bedroom': if(device === 'light'){ func.roomtype(1,state); console.log("Bedroom light"); } else if(device === 'fan'){ func.roomtype(6,state); console.log("Bedroom fan"); } break; // Kitchen light on/off case 'Kitchen': if(device === 'light'){ func.roomtype(2,state); console.log("Kitchen light"); } else if(device ==='fan'){ func.roomtype(7,state); console.log("Kitchen chimney"); } break; // Living room light on/off case 'living room': if(device ==='light'){ func.roomtype(3,state); console.log("Living room light"); } else if(device ==='fan'){ func.roomtype(8,state); console.log("Living room fan"); } break; // Drawing room light on/off case 'drawing room': if(device ==='light'){ func.roomtype(4,state); console.log("Drawing room light"); } else if(device ==='fan'){ func.roomtype(9,state); console.log("Drawing room fan"); } break; case 'main hall': if(device ==='door'){ func.roomtype(10,state); console.log(" Main hall door "); } else if(device ==='light'){ func.roomtype(11,state); console.log("main hall light"); } break; // for turning all lights on/off case 'all':func.roomtype(0,state); console.log("Bathroom light"); func.roomtype(1,state); console.log("Bedroom light"); func.roomtype(2,state); console.log("Kitchen light"); func.roomtype(3,state); console.log("Living room light"); func.roomtype(4,state); console.log("Drawing room light"); func.roomtype(11,state); console.log("Hall room light"); var date=new Date(); var info=fs.readFileSync('/var/www/html/jsonpage/info.json','utf-8'); if(info==""){ write a fresh json file (array of objects in this case) } else{ append the data into the json file } read the new json file contents if(greater than certain length){ mail it to you and delete the json records } } else{ // for controlling light brightness using PWM var room=message.slots[0].rawValue; // room type slot console.log(room); var device=message.slots[1].rawValue; // device type slot console.log(device); var brightness= message.slots[2].rawValue; // brightness value slot console.log(brightness); switch(room){ // set bathroom light brightness case 'bathroom': if (device ==='light' && brightness === 'seventy five'){ pwmlight.pwmthreequater(0); console.log('Brightness is set to 75 ') } else if (device === 'light' && brightness === 'fifty'){ pwmlight.pwmhalf(0); console.log('Brightness is set to 50 ') } else if (device ==='light' && brightness === 'twenty five'){ pwmlight.pwmonequat(0); console.log('Brightness is set to 25 ') } else if (device ==='light' && brightness === 'zero'){ pwmlight.pwmzero(0); console.log('Brightness is set to 0 ') } else if (device ==='light' && brightness === 'hundred'){ pwmlight.pwmzero(0); console.log('Brightness is set to 100 ') } break; // set bedroom light brightness case 'bedroom' : if (device === 'light' && brightness === 'hundred'){ pwmlight.pwmfull(1); console.log("Brightness is set to 100") } else if (device === 'light' && brightness === 'seventy five'){ pwmlight.pwmthreequater(1); console.log("Brightness is set to 75") } else if (device === 'light' && brightness === 'fifty'){ pwmlight.pwmhalf(1); console.log("Brightness is set to 50") } else if (device === 'light' && brightness === 'twenty five'){ pwmlight.pwmonequat(1); console.log("Brightness is set to 25") } else if (device === 'light' && brightness === 'zero'){ pwmlight.pwmzero(1); console.log("Brightness is set to 0") } break; // Set Kitchen light brightness case 'Kitchen' : if (device === 'light' && brightness === 'hundred'){ pwmlight.pwmfull(2); console.log("Brightness is set to 100") } else if (device === 'light' && brightness === 'seventy five'){ pwmlight.pwmthreequater(2); console.log("Brightness is set to 75") } else if (device === 'light' && brightness === 'fifty'){ pwmlight.pwmhalf(2); console.log("Brightness is set to 50") } else if (device === 'light' && brightness === 'twenty five'){ pwmlight.pwmonequat(2); console.log("Brightness is set to 25") } else if (device === 'light' && brightness === 'zero'){ pwmlight.pwmonequat(2); console.log("Brightness is set to 0") } break; // Set Living room brightness case 'living room': if (device === 'light' && brightness === 'hundred'){ pwmlight.pwmfull(3); console.log("Brightness is set to 100") } else if (device === 'light' && brightness === 'seventy five'){ pwmlight.pwmthreequater(3); console.log("Brightness is set to 75") } else if (device === 'light' && brightness === 'fifty'){ pwmlight.pwmhalf(3); console.log("Brightness is set to 50") } else if (device === 'light' && brightness === 'twenty five'){ pwmlight.pwmonequat(3); console.log("Brightness is set to 25") } else if (device === 'light' && brightness === 'zero'){ pwmlight.pwmonequat(3); console.log("Brightness is set to 0") } break; //Set drawing room brightness case 'drawing room': if (device === 'light' && brightness === 'hundred'){ pwmlight.pwmfull(4); console.log("Brightness is set to 100") } else if (device === 'light' && brightness === 'seventy five'){ pwmlight.pwmthreequater(4); console.log("Brightness is set to 75") } else if (device === 'light' && brightness === 'fifty'){ pwmlight.pwmhalf(4); console.log("Brightness is set to 50") } else if (device === 'light' && brightness === 'twenty five'){ pwmlight.pwmonequat(4); console.log("Brightness is set to 25") } else if (device === 'light' && brightness === 'zero'){ pwmlight.pwmzero(4); console.log("Brightness is set to 0") } break; } var date=new Date(); read json file info.json if(info==""){ write a fresh json file (array of objects in this case) } else{ append the data into the json file } read the new json file contents if(greater than certain length){ mail it to you and delete the json records } } // Expect error if `on` or `off` is not heard catch(e){ console.log(e) } break; // * On Conversation End case sessionEnd: everloop.stopWaiting(); console.log('Session Ended\n'); break; } });
Once done with all the setup.
Next, Open shell and run
cd js-matrix-core-app
node assistant.js
Open another shell and run
cd /var/www/html
node server.js
Open browser
localhost:8080/index.html
Connections
Relay ==> Matrix Voice
- 5V ==> 5V
- GND ==>GND
- Signal1 ==> GPIO0 (DF0)
- Signal2 ==> GPIO1 (DF1)
- Signal3 ==> GPIO2 (DF2)
- Signal4 ==> GPIO3 (DF3)
- Signal5 ==> GPIO5 (DF5)
- signal6 ==> GPIO11 (DF11)
Servo Motor ==> Matrix Voice
- 5V ==> 5V
- GND ==> GND
- Signal ==> GPIO10(DF10)
Program
assistant.js
///////////// //VARIABLES// ///////////// var mqtt = require('mqtt'); var client = mqtt.connect('mqtt://localhost', { port: 1883 }); var func =require('./func.js'); var everloop = require('./everloop.js'); var pwmlight = require('./pwm.js'); var snipsUserName = 'ruchir'; // snips username var wakeword = 'hermes/hotword/default/detected'; var sessionEnd = 'hermes/dialogueManager/sessionEnded'; var lightState = 'hermes/intent/'+snipsUserName+':lights'; // intent name ////////////// //ON CONNECT// ////////////// client.on('connect', function() { console.log('Connected to Snips MQTT server\n'); client.subscribe('hermes/hotword/default/detected'); client.subscribe('hermes/dialogueManager/sessionEnded'); client.subscribe(lightState); }); ////////////// //ON MESSAGE// ////////////// client.on('message', function(topic,message) { var message = JSON.parse(message); switch(topic) { // * On Wakeword case wakeword: everloop.startWaiting(); console.log('Wakeword Detected'); break; // * On Light State Change case lightState: // Turn lights On/Off try{ // controlling light using PWM if(message.slots[0].rawValue==='on' || message.slots[0].rawValue==='off'|| message.slots[0].rawValue==='open' || message.slots[0].rawValue==='close'){ var room=message.slots[1].rawValue; // room types slot console.log(room); var state=message.slots[0].rawValue; // state type slot console.log(state); var device=message.slots[2].rawValue;// device type slot console.log(device); switch(room){ // Bathroom light on/off case 'bathroom': if(device ==='light'){ func.roomtype(0,state); console.log("Bathroom light"); } else if(device ==='fan'){ func.roomtype(5,state); console.log("Bathroom fan"); } break; // Bedroom light on/off case 'bedroom': if(device === 'light'){ func.roomtype(1,state); console.log("Bedroom light"); } else if(device === 'fan'){ func.roomtype(6,state); console.log("Bedroom fan"); } break; // Kitchen light on/off case 'Kitchen': if(device === 'light'){ func.roomtype(2,state); console.log("Kitchen light"); } else if(device ==='fan'){ func.roomtype(7,state); console.log("Kitchen chimney"); } break; // Living room light on/off case 'living room': if(device ==='light'){ func.roomtype(3,state); console.log("Living room light"); } else if(device ==='fan'){ func.roomtype(8,state); console.log("Living room fan"); } break; // Drawing room light on/off case 'drawing room': if(device ==='light'){ func.roomtype(4,state); console.log("Drawing room light"); } else if(device ==='fan'){ func.roomtype(9,state); console.log("Drawing room fan"); } break; case 'main hall': if(device ==='door'){ func.roomtype(10,state); console.log(" Main hall door "); } else if(device ==='light'){ func.roomtype(11,state); console.log("main hall light"); } break; // for turning all lights on/off case 'all':func.roomtype(0,state); console.log("Bathroom light"); func.roomtype(1,state); console.log("Bedroom light"); func.roomtype(2,state); console.log("Kitchen light"); func.roomtype(3,state); console.log("Living room light"); func.roomtype(4,state); console.log("Drawing room light"); func.roomtype(11,state); console.log("Hall room light"); } } else{ // for controlling light brightness using PWM var room=message.slots[0].rawValue; // room type slot console.log(room); var device=message.slots[1].rawValue; // device type slot console.log(device); var brightness= message.slots[2].rawValue; // brightness value slot console.log(brightness); switch(room){ // set bathroom light brightness case 'bathroom': if (device ==='light' && brightness === 'seventy five'){ pwmlight.pwmthreequater(0); console.log('Brightness is set to 75 ') } else if (device === 'light' && brightness === 'fifty'){ pwmlight.pwmhalf(0); console.log('Brightness is set to 50 ') } else if (device ==='light' && brightness === 'twenty five'){ pwmlight.pwmonequat(0); console.log('Brightness is set to 25 ') } else if (device ==='light' && brightness === 'zero'){ pwmlight.pwmzero(0); console.log('Brightness is set to 0 ') } else if (device ==='light' && brightness === 'hundred'){ pwmlight.pwmzero(0); console.log('Brightness is set to 100 ') } break; // set bedroom light brightness case 'bedroom' : if (device === 'light' && brightness === 'hundred'){ pwmlight.pwmfull(1); console.log("Brightness is set to 100") } else if (device === 'light' && brightness === 'seventy five'){ pwmlight.pwmthreequater(1); console.log("Brightness is set to 75") } else if (device === 'light' && brightness === 'fifty'){ pwmlight.pwmhalf(1); console.log("Brightness is set to 50") } else if (device === 'light' && brightness === 'twenty five'){ pwmlight.pwmonequat(1); console.log("Brightness is set to 25") } else if (device === 'light' && brightness === 'zero'){ pwmlight.pwmzero(1); console.log("Brightness is set to 0") } break; // Set Kitchen light brightness case 'Kitchen' : if (device === 'light' && brightness === 'hundred'){ pwmlight.pwmfull(2); console.log("Brightness is set to 100") } else if (device === 'light' && brightness === 'seventy five'){ pwmlight.pwmthreequater(2); console.log("Brightness is set to 75") } else if (device === 'light' && brightness === 'fifty'){ pwmlight.pwmhalf(2); console.log("Brightness is set to 50") } else if (device === 'light' && brightness === 'twenty five'){ pwmlight.pwmonequat(2); console.log("Brightness is set to 25") } else if (device === 'light' && brightness === 'zero'){ pwmlight.pwmonequat(2); console.log("Brightness is set to 0") } break; // Set Living room brightness case 'living room': if (device === 'light' && brightness === 'hundred'){ pwmlight.pwmfull(3); console.log("Brightness is set to 100") } else if (device === 'light' && brightness === 'seventy five'){ pwmlight.pwmthreequater(3); console.log("Brightness is set to 75") } else if (device === 'light' && brightness === 'fifty'){ pwmlight.pwmhalf(3); console.log("Brightness is set to 50") } else if (device === 'light' && brightness === 'twenty five'){ pwmlight.pwmonequat(3); console.log("Brightness is set to 25") } else if (device === 'light' && brightness === 'zero'){ pwmlight.pwmonequat(3); console.log("Brightness is set to 0") } break; //Set drawing room brightness case 'drawing room': if (device === 'light' && brightness === 'hundred'){ pwmlight.pwmfull(4); console.log("Brightness is set to 100") } else if (device === 'light' && brightness === 'seventy five'){ pwmlight.pwmthreequater(4); console.log("Brightness is set to 75") } else if (device === 'light' && brightness === 'fifty'){ pwmlight.pwmhalf(4); console.log("Brightness is set to 50") } else if (device === 'light' && brightness === 'twenty five'){ pwmlight.pwmonequat(4); console.log("Brightness is set to 25") } else if (device === 'light' && brightness === 'zero'){ pwmlight.pwmzero(4); console.log("Brightness is set to 0") } break; } } } // Expect error catch(e){ console.log(e) } break; // * On Conversation End case sessionEnd: everloop.stopWaiting(); console.log('Session Ended\n'); break; } });
everloop.js
///////////// //VARIABLES// ///////////// var zmq = require('zeromq');// Asynchronous Messaging Framework var matrix_io = require('matrix-protos').matrix_io;// Protocol Buffers for MATRIX function var matrix_ip = '127.0.0.1';// Local IP var matrix_everloop_base_port = 20021;// Port for Everloop driver var matrix_device_leds = 0;// Holds amount of LEDs on MATRIX device var methods = {};// Declaration of method controls at the end var waitingToggle = false; var counter = 0; /////////////////// //KEEP ALIVE PORT// /////////////////// // Create a Pusher socket var pingSocket = zmq.socket('push') // Connect Pusher to Keep-alive port pingSocket.connect('tcp://' + matrix_ip + ':' + (matrix_everloop_base_port + 1)); // Send a single ping pingSocket.send(''); ////////////// //ERROR PORT// ////////////// // Create a Subscriber socket var errorSocket = zmq.socket('sub'); // Connect Subscriber to Error port errorSocket.connect('tcp://' + matrix_ip + ':' + (matrix_everloop_base_port + 2)); // Connect Subscriber to Error port errorSocket.subscribe(''); // On Message errorSocket.on('message', function(error_message){ console.log('Error received: ' + error_message.toString('utf8'));// Log error }); //////////////////// //DATA UPDATE PORT// //////////////////// // Create a Subscriber socket var updateSocket = zmq.socket('sub'); // Connect Subscriber to Data Update port updateSocket.connect('tcp://' + matrix_ip + ':' + (matrix_everloop_base_port + 3)); // Subscribe to messages updateSocket.subscribe(''); // On Message updateSocket.on('message', function(buffer){ var data = matrix_io.malos.v1.io.EverloopImage.decode(buffer);// Extract message matrix_device_leds = data.everloopLength;// Save MATRIX device LED count }); ///////////// //BASE PORT// ///////////// // Create a Pusher socket var configSocket = zmq.socket('push'); // Connect Pusher to Base Port configSocket.connect('tcp://' + matrix_ip + ':' + matrix_everloop_base_port); // Create an empty Everloop image var image = matrix_io.malos.v1.io.EverloopImage.create(); setInterval(function(){ // Turns off all LEDs if (waitingToggle == false) { for (var i = 0; i < matrix_device_leds; ++i) { // Set individual LED value image.led[i] = { red: 0, green: 0, blue: 0, white: 0 }; } }; // Creates pulsing LED effect if (waitingToggle == true) { for (var i = 0; i < matrix_device_leds; ++i) { // Set individual LED value image.led[i] = { red: (Math.round((Math.sin(counter) + 1) * 100) + 10), green: (Math.round((Math.sin(counter) + 1) * 100) + 10), blue: (Math.round((Math.sin(counter) + 1) * 100) + 10),// Math used to make pulsing effect white: 0 }; } }; counter = counter + 0.2; // Store the Everloop image in MATRIX configuration var config = matrix_io.malos.v1.driver.DriverConfig.create({ 'image': image }); // Send MATRIX configuration to MATRIX device if(matrix_device_leds > 0) { configSocket.send(matrix_io.malos.v1.driver.DriverConfig.encode(config).finish()); }; },50); /////////////////// //WAITING METHODS// /////////////////// methods.startWaiting = function() { waitingToggle = true; }; methods.stopWaiting = function() { waitingToggle = false; }; module.exports = methods;
func.js
var everloop = require('./everloop.js'); var pwmlight = require('./pwm.js'); var methods={}; methods.roomtype = function(pin,state){ if (state === 'on'){ pwmlight.lightOn(pin);// passing arguments everloop.stopWaiting(); console.log('light is turned On'); } else if(state === 'off'){ pwmlight.lightOff(pin); everloop.stopWaiting(); console.log('light is turned Off'); } else if(state === 'open'){ pwmlight.dooropen(pin); everloop.stopWaiting(); console.log('door is open'); } else if(state === 'close'){ pwmlight.doorclose(pin); everloop.stopWaiting(); console.log('door is close'); } }; module.exports = methods;
pwm.js
// PWM functions for controlling lights var matrix = require("@matrix-io/matrix-lite"); var methods = {};// Declaration of method controls at the end methods.pwmfull = function(pin){ matrix.gpio.setFunction(pin, 'PWM'); matrix.gpio.setMode(pin, 'output'); matrix.gpio.setPWM({ pin: pin, percentage: 100, frequency: 60 }); }; methods.pwmthreequater = function(pin){ matrix.gpio.setFunction(pin, 'PWM'); matrix.gpio.setMode(pin, 'output'); matrix.gpio.setPWM({ pin: pin, percentage: 75, frequency: 60 }); }; methods.pwmhalf = function(pin){ matrix.gpio.setFunction(pin, 'PWM'); matrix.gpio.setMode(pin, 'output'); matrix.gpio.setPWM({ pin: pin, percentage: 50, frequency: 60 }); }; methods.pwmonequat = function(pin){ matrix.gpio.setFunction(pin, 'PWM'); matrix.gpio.setMode(pin, 'output'); matrix.gpio.setPWM({ pin: pin, percentage: 25, frequency: 60 // min 36 }); }; methods.pwmzero = function(pin){ matrix.gpio.setFunction(pin, 'PWM'); matrix.gpio.setMode(pin, 'output'); matrix.gpio.setPWM({ pin: pin, percentage: 0, frequency: 60 }); }; methods.lightOn = function(pin){ matrix.gpio.setFunction(pin, 'PWM'); matrix.gpio.setMode(pin, 'output'); matrix.gpio.setPWM({ pin: pin, percentage: 100, frequency: 60 }); }; methods.lightOff = function(pin){ matrix.gpio.setFunction(pin, 'PWM'); matrix.gpio.setMode(pin, 'output'); matrix.gpio.setPWM({ pin: pin, percentage: 0, frequency: 60 }); }; //For controlling doors methods.dooropen = function(pin){ matrix.gpio.setFunction(pin, 'PWM'); matrix.gpio.setMode(pin, 'output'); matrix.gpio.setServoAngle({ pin: pin, angle: 160, // minimum pulse width for a PWM wave (in milliseconds) min_pulse_ms:0.8 // 0.8 }); }; methods.doorclose = function(pin){ matrix.gpio.setFunction(pin, 'PWM'); matrix.gpio.setMode(pin, 'output'); matrix.gpio.setServoAngle({ pin: pin, angle: 10, // minimum pulse width for a PWM wave (in milliseconds) min_pulse_ms:0.8 // 0.8 }); }; module.exports = methods;
Result
Top Comments