Create a custom Smart Assistant device using Web Technologies – Re-Upload

By Raddy in CSS JavaScript ·

Have you ever wondered if you could make your own smart Assistant device that is tailored to your needs? Well, I did and I figured out that it is actually fairly easy to do using web technologies and a few API’s.

So let’s start with what is a smart assistant device and what do they actually do? Let’s have a look at the definition from Wikipedia.

An automated personal assistant or an Intelligent Personal Assistant is a mobile software agent that can perform tasks, or services, on behalf of an individual based on a combination of user input, location awareness, and the ability to access information from a variety of online sources (such as weather conditions, traffic congestion, news, stock prices, user schedules, retail prices, etc.).

Wikipedia

Popular smart assistants include Google Assistant, Alexa, Siri and the new Celia from Huawei. They are actually fairly cheap to buy now.

In this blog post, we will look at how we can create our own custom assistant using web technologies. We will be using HTML, CSS, and JavaScript to build the project and to make the device smart, we will throw in some API’s such as the Open Weather API, YouTube API and Unsplash API.

If you don’t like reading you are in luck because I’ve already recorded everything on a video tutorial for you to watch.

First of all, before we begin, let’s have a look at a demo video of how our smart assistant will work. Obviously you can customize yours the way you want and add the features that are helpful to you.

Demo

YouTube API:
https://console.developers.google.com/apis/library/

Open Weather API:
https://openweathermap.org/api

Unsplash API:
https://unsplash.com/developers

Odometer JS:
https://github.hubspot.com/odometer/docs/welcome/

Let’s start with the HTML. Basically as explained in the video tutorial each section will act as a individual page. You can also make separate documents for each page if you like, but my application is fairly small so this is a good way of doing it.

I’ve included Odometer library files to make the YouTube API counter spin. Annyang is the speech recognition library that i will be using.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Gorilla Hub</title>
    <link rel="stylesheet" href="css/styles.css">
    <link href="https://fonts.googleapis.com/css?family=Work+Sans:400,700&display=swap" rel="stylesheet"> 
    <link rel="stylesheet" href="css/odometer-theme-default.css">
    <link rel="stylesheet" href="css/owfont-regular.min.css">
</head>
<body>
    
    <div class="wrapper">

        <a name="anchorHome"></a>
        <section id="home">
            <!-- <div class="testlink"><a href="#anchorWeather">Go Weather</a></div> -->
            <div id="time">00:00</div>
            <div id="notifications">Notifications</div>
            <div id="demo">Say "Gorilla Hub show weather..."</div>
            <div id="subcount">
                <div id="subcount__title">YouTube Subscribers</div>
                <div id="subcount__number" class="odometer">0000</div>
            </div>
        </section>

        <a name="anchorWeather"></a>
        <section id="weather">
            <!-- <div class="testlink"><a href="#anchorHome">Go Home</a></div> -->
            <div id="wheaterstuff">
                <div class="weather__icon owf"></div>
                <div class="weather__title">Weather</div> 
            </div>
        </section>
    </div> 
    
    <script src="js/odometer.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/annyang/2.6.1/annyang.min.js"></script>
    <script src="js/script.js"></script>
</body>
</html>

CSS

* { box-sizing: border-box; }

body {
    margin: 0;
    padding: 0;
    font-family: 'Work Sans', sans-serif;
    background-color: bisque;
    background-image: url("../img/sf1.jpg");
    background-size: cover;
    color: #fff;
}

.wrapper {
    width: 100vw;
    height: 100vh;
    overflow: hidden;
    scroll-behavior: smooth; 
}

section {
    position: relative;
    padding: 1em;
    width: 100vw;
    height: 100vh;
    font-size: 3em;
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: repeat(3, 1fr);
    grid-template: "a"
                   "b"
                   "c";
}

#time {
    grid-area: c;
    justify-self: left;
    align-self: end;
    line-height: 0.7;
    font-weight: 700;
}

#notifications {
    grid-area: a;
    justify-self: end;
    font-size: 0.5em;
}

#demo {
    grid-area: c;
    justify-self: end;
    align-self: end;
    font-size: 0.5em;
    font-style: italic;
    opacity: 0.6;
}

#subcount {
    grid-area: b;
    justify-self: center;
    align-self: center;
    text-align: center;
}

#subcount #subcount__title {
    font-size: 0.5em;
}

#subcount #subcount__number {
    display: block;
}

#weather {
    background-size: cover;
}
#wheaterstuff {
    grid-area: b;
    justify-self: center;
    align-self: center;
    text-align: center;
    text-transform: capitalize;
}

.testlink {
    grid-area: a;
    justify-content: start;
    font-size: 0.5em;
}


@keyframes fadeOut {
    0% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}


@keyframes fadeIn {
    0% {
        display: block;
        opacity: 0;
    }
    100% {
        opacity: 1;
    }
}

And here is the speech recognition code. Create a file called script.js and include that file in your js folder. I’ve also left the language settings for you.

if (annyang) {
    console.log("We have annyang");

    // annyang.setLanguage('bg');

    var commands = {
        'Gorilla Hub show home' : home,
        'show home' : home,
        'Gorilla Hub show weather' : weather,
        'show weather' : weather

        // 'първа страница' : home,
        // 'време' : weather
    }


    function home() {
        console.log("Home");
        location.hash = "anchorHome";
    }

    function weather(){
        console.log("Weather");
        location.hash = "anchorWeather";
    }

    // Add Commands
    annyang.addCommands(commands);

    // Start listening
    annyang.start();

}// Time
setInterval(() => {
    let today = new Date();
    let h = today.getHours();
    let m = today.getMinutes();
    m = checkTime(m);
    let time = h + ":" + m;
    document.getElementById("time").innerHTML = time;
}, 1);

function checkTime(i){
    if(i < 10) {
        i = "0" + i;
    }
    return i;
}

// Notifications
function getWeekDay(date){
    newDate = new Date();
    let today = newDate.getDay();
    let notificationMsg = document.getElementById("notifications");
    if(today == 5) {
        notificationMsg.innerHTML = "Get the bin out...";
    } else {
        notificationMsg.innerHTML = "No new notifications";
    }
}

// Get Subscribers
const youtubeKey = ' ADD API KEY HERE ';
const youtubeUsername = 'UCvXscyQ0cLzPZeNOeXI45Sw';
const odometer = document.querySelector('.odometer');
const delay = 1000; // 10 min
// var delay = 60 * 60 * 1000; // 1 hour in msec

function getSubscribers() {

    fetch(`https://www.googleapis.com/youtube/v3/channels?part=statistics&id=${youtubeUsername}&key=${youtubeKey}`)
    .then(response => {
        return response.json()
    }) 
    .then(data => { 
        console.log(data);
        // console.log(data["items"][0].statistics.subscriberCount);
        var subCount = parseInt(data["items"][0].statistics.subscriberCount);
        odometer.innerHTML = subCount + i; 
    })
    .catch(err => {

    })
    i++;
}

setInterval(() => {
    getWeekDay();
    getSubscribers();
}, delay);


// Weather
const proxy = 'https://cors-anywhere.herokuapp.com/';
let weatherIcon = document.querySelector('.weather__icon');
let weatherTitle = document.querySelector('.weather__title');

function getWeather() {
    fetch(`https://api.openweathermap.org/data/2.5/weather?q=London,uk&appid= ADD API ID HERE`)
    .then(response => {
        return response.json()
    }) 
    .then(data => { 
        console.log(data);
        weatherTitle.innerHTML = data.weather[0].description;
        weatherIcon.classList.add(`owf-${data.weather[0].id}`);
        getWeatherPhoto(data.weather[0].description);
    })
    .catch(err => {
    })
}


// Unsplash change weather photo based on weather
let weatherWrapper = document.querySelector('#weather');
function getWeatherPhoto(weather) {
    let unsplashApi = 'https://api.unsplash.com/search/photos?client_id= ADD API KEY HERE &page=1&per_page=1&query='+weather;
    fetch(unsplashApi)
    .then(response => {
        return response.json()
    }) 
    .then(data => { 
        weatherWrapper.setAttribute('style', 'background-image:url('+ data.results[0].urls.regular +');');
    }) 
    .catch(err => {
    })
}

function playSound() {
    // const audio = document.querySelector("#gorilla");
    // audio.currentTime = 0;
    // audio.play();
}

getWeatherPhoto();
getSubscribers();
getWeekDay();
getWeather();


if (annyang) {
    //annyang.setLanguage('bg');
 
    // Let's define our first command. First the text we expect, and then the function it should call
    var commands = {
        'Gorilla hub show home' : home,
        'show home' : home,
        'Gorilla hub show weather': weather,
        'show weather': weather,
        'Gorilla hub show inspirational quote' : quote,
        'quote' : quote
 
        // 'къща' : home,
        // 'първа страница' : home,
        // 'време': weather,
        // 'покажи времето': weather,
        // '5' : quote,
        // '6' : quote
    };

    function home(){
        console.log("Home")
        playSound(); 
        location.hash = "anchorHome";
    }

    function weather(){
        console.log("Weather")
        playSound(); 
        location.hash = "anchorWeather";
    }

    function quote(){
        playSound(); 
        location.hash = "3";
    }

    // Add our commands to annyang
    annyang.addCommands(commands);

    // Start listening. You can call this here, or attach this call to an event, button, etc.
    annyang.start();
}if (annyang) {
    console.log("We have annyang");

    // annyang.setLanguage('bg');

    var commands = {
        'Gorilla Hub show home' : home,
        'show home' : home,
        'Gorilla Hub show weather' : weather,
        'show weather' : weather

        // 'първа страница' : home,
        // 'време' : weather
    }


    function home() {
        console.log("Home");
        location.hash = "anchorHome";
    }

    function weather(){
        console.log("Weather");
        location.hash = "anchorWeather";
    }

    // Add Commands
    annyang.addCommands(commands);

    // Start listening
    annyang.start();

}

If you have copied the code and included all files required, you should by now have a voice command device fully working.

Thank you for reading this article. Please consider subscribing to my YouTube Channel.

Leave a Reply

Your email address will not be published. Required fields are marked *