Google Home Message Broadcast System [Node.js]

Introduction

If you are a tech nerd like me, you just have collected random devices as you go on walking through life. One of my favorites is called a Google Home Mini. I got these bad boys at BestBuy for around $35 during black Friday and have one set up in 3 different rooms.

The best part of this is that I can set timers, reminders, or ask what the weather is when I’m to lazy to check. With my house slowly moving towards home customization, one of the features I wanted was a household notification system. Turns out I have a Google Home Mini that can do just that… broadcast a custom message.

Demo

Prerequisites

  • Node.js
    • castv2-client
    • google-tts-api
  • Google Home/Google Home Mini
  • Assigning a static IP to Google Home/Google Home Mini

Step 1: Installing & setup of project

This one should be a breeze. If you are using straight up command line use NPM to install the packages. I currently use WebStorm IDE from JetBrains however to write all my Node.JS code but all of this tutorial will be done assuming you use good old fashioned notepad.exe (plz don’t actually)

Create a new directory in your file system and open up your command line/terminal then run the following commands.

cd /path/to/directory
npm init//Keep pressing enter till it finishes project generation
npm install castv2-client
npm install google-tts-api

Once your project has been initialized create a JS file in that directory and open it, you can name it whatever you’d like but I named mine GoogleHomeBroadcaster.js

Step 2: Import packages and define terms

In order to use the packages we install we have to declare them. At the top of our file add

var Client = require('castv2-client').Client;
var DefaultMediaReceiver = require('castv2-client').DefaultMediaReceiver;
const googleTTS = require('google-tts-api');

If you already know about these packages or don’t care to know exactly what they are, feel free to skip onto the next section.

  • castv2-client
    • A Chromecast client based on the new (CASTV2) protocol. This is how we communicate to our Google Home/Google Home Mini.
  • google-tts-api
    • An API from google that converts our plaintext string into a mp3 file that gets played on our Google Home/Google Home Mini
  • Client
    • This is our object that allows us to control our Google Home, it references the speaker itself and allows us to alter it like change the volume on it.
  • DefaultMediaReceiver
    • This is the default client provided by the Google API. Handles basic audio streaming. You can read more about the DefaultMediaReciever and how to create your own at the above link

Step 3: Create our Player

You can view the full code below or go through each step

App Player Code (SPOILER)
var App = {
    playin: false,
    DeviceIp: "",
    Player: null,
    GoogleHome: function (host, url) {
        var client = new Client();
        client.connect(host, function () {
            client.launch(DefaultMediaReceiver, function (err, player) {
                client.setVolume({ level: 1 });
                var media = {
                    contentId: url,
                    contentType: 'audio/mp3',
                    streamType: 'BUFFERED'
                };
                App.Player = player;
                App.Player.load(media, { autoplay: true }, function (err, status) {
                    App.Player.on('status', function (status) {
                        if (status.playerState === "IDLE" && App.playin === false) {
                            client.close();
                        }
                    });
                });
            });
        });
        client.on('error', function (err) {
            console.log('Error: %s', err.message);
            client.close();
            callback('error');
        });
    }
};

Define our App along with our private variables we are going to use

var App = {
    playin: false,
    DeviceIp: "",
    Player: null,

Define our function “GoogleHome” with parameters

  • host: The IP of our Google Home Mini
  • url: The url generated using Google’s TTS API
GoogleHome: function (host, url) {

Instantiate a new client object and then connect to our Google Home through the host variable (IP of the device)

 var client = new Client();
 client.connect(host, function () {

We then launch the Default media receiver which notifies our Google Home that we are going to be sending some audio.

We set the volume to 1F, which implies 100% volume. Range [0.0-1.0]

Generate the payload that is sent to our media reciever, ContentID is the url of our Mp3 generated from google tts api, content type is the type of media, and stream type denotes the audio is buffered.

We then load our payload into our DefaultMediaReciever and set autoplay to on for it to automatically start. We then listen to the status so that when the player is done with the audio we can close the connection

            client.launch(DefaultMediaReceiver, function (err, player) {
                client.setVolume({ level: 1 });
                var media = {
                    contentId: url,
                    contentType: 'audio/mp3',
                    streamType: 'BUFFERED'
                };
                App.Player = player;
                App.Player.load(media, { autoplay: true }, function (err, status) {
                    App.Player.on('status', function (status) {
                        if (status.playerState === "IDLE" && App.playin === false) {
                            client.close();
                        }
                    });
                });
            });
        });

We also have an error function to handle any errors

        client.on('error', function (err) {
            console.log('Error: %s', err.message);
            client.close();
        });
    }
};

Step 4: Implement Run + Google TTS

Now our goal is to convert our text into an mp3 file using Google’s Talk to Speech API. All it needs is a string with the text you want to translate. This function will then translate the text and then broadcast it to your google home mini. It is part of the App object so just add it after our “GoogleHome” function with a comma after.

    run: function (ip, text) {
        App.DeviceIp = ip;
        const url = googleTTS.getAudioUrl(text, {
            lang: 'en-US',
            slow: false,
            host: 'https://translate.google.com',
        });
        App.GoogleHome(App.DeviceIp, url, function (res) {
            console.log(res);
        })
    }

Step 4.5 (Optional): Broadcast to multiple devices

Right now you should be good to go with a single Google Home Mini using the “run” function. Since I have multiple Google Home’s, I just wrote a function to execute the run for all the devices. The “ips” variable is just a string “192.168.68.105,192.168.68.107,192.168.68.124” which when split represents the IP of my different devices.

broadcast: function(text){
        const ips = process.env.GOOGLEHOME_IPS.split(","); //From config, 192.168.68.105,192.168.68.107,192.168.68.124
        for (var s of ips){
            App.run(s, text);
        

Step 5: Run our program

This is definitely the easiest part! We just have to call our program and it shall broadcast whatever you have set as your string. We can run our program by using the code below.

App.run("192.168.68.124", "Test message sent to one device");
App.broadcast("Broadcasted to all of the devices"); //Only works if you did step 4.5
Full Code (SPOILER)
var Client = require('castv2-client').Client;
var DefaultMediaReceiver = require('castv2-client').DefaultMediaReceiver;
const googleTTS = require('google-tts-api');

var App = {
    playin: false,
    DeviceIp: "",
    Player: null,
    GoogleHome: function (host, url) {
        var client = new Client();
        client.connect(host, function () {
            client.launch(DefaultMediaReceiver, function (err, player) {
                client.setVolume({ level: 1 });
                var media = {
                    contentId: url,
                    contentType: 'audio/mp3',
                    streamType: 'BUFFERED'
                };
                App.Player = player;
                App.Player.load(media, { autoplay: true }, function (err, status) {
                    App.Player.on('status', function (status) {
                        if (status.playerState === "IDLE" && App.playin === false) {
                            client.close();
                        }
                    });
                });
            });
        });
        client.on('error', function (err) {
            console.log('Error: %s', err.message);
            client.close();
        });
    },
    run: function (ip, text) {
        App.DeviceIp = ip;
        const url = googleTTS.getAudioUrl(text, {
            lang: 'en-US',
            slow: false,
            host: 'https://translate.google.com',
        });
        App.GoogleHome(App.DeviceIp, url, function (res) {
            console.log(res);
        })
    },
    broadcast: function(text){
        const ips = process.env.GOOGLEHOME_IPS.split(","); //From config, 192.168.68.105,192.168.68.107,192.168.68.124
        for (var s of ips){
            App.run(s, text);
        }
    }
};
App.run("192.168.68.124", "Test message sent to one device");
//App.broadcast("Broadcasted to all of the devices"); //Only works if you did step 4.5

You can play any audio file if you have the url, youc an abstract it to a function and call it from anywhere in your code, (smarthome ring doorbell).

Leave a Reply

Your email address will not be published.