[Release] Google Home Assistant Relay Driver (v1 and v2)- text to speech on Google Home devices



I prefer PM2 to forever... But each to their own, as they say.


I prefer PM2 as well. That is why my personal instructions include it instead of Forever

To each his own. The instructions that I have shared are really just my personal notes for setting up a RPi to run Assistant-Relay, and keep it running. I shared them in an attempt to help others (like me) who are not experts on RPi/Linux.


But you have to install it first. And if the instructions don't tell you to install pm2, then that is missing, isn't it?


That's fine...but if the instructions don't tell you to install pm2, then they are obviously missing that step, aren't they? Why the hostility?


No hostility intended. But keep in mind those weren't really instructions, they were NOTES.

I would guess that most are OK with pointing out where notes can be better/more complete, though.


And that is exactly what I did. I'm sorry, but I didn't take the time to call up @ogiewon's notes and annotate them....i merely answered the question of the person who posted. Period. Boy, you people really don't give anyone any slack do you?


For what it's worth, I followed them without a problem.


LMAO....you people need to stop taking things so personally. Obviously if someone else couldn't, then they couldn't. I don't see what the issue is with recommending something be added. Is it really that personal an assault to ask someone to add a line to a set of instructions?


My notes already include instructions on how to install and use PM2. If anyone finds any errors and would like to provide feedback, I’m all ears.


I only said

sudo npm install pm2@latest -g

Worked better for me.
Twas all.
Fun fact, somehow this installation caused homebridge to stop working in it's container, even through soft reboots.
A hard power cycle fixed it...

All is well though. Thanks @ogiewon


Do you then need a systemd service to start the relay each time you start the pi? forever is easy since it only need one command to run and can be done right from rc.local. Just easier for someone who's never used an RPi before.


Even simpler than that... PM2 takes care of everything... no editing of any files required. It handles auto starting node apps at startup, and keeps them running.

I’m not saying it is better than forever. I just feel it is a more polished product, which makes it use simpler for me.


Well, you have to enable pm2 then, right? LOL...i mean, it can't work by magic. You must have to run systemctl enable pm2? Something? Or once its installed it runs and there's no stopping it? LOL


It’s all documented in my instructions, which are basically the same as yours, except for using pm2. I stole most of my instructions shamelessly from your GitHub repo! :wink:


You just can't tell me? I guess I won't know then. LMAO

Wow...."pm2 startup" would have killed you?!?

It doesn't bother me at all....i was asking a question of how pm2 works vs forever. LOL. I'm not just going to take your word for it when I have a solution that works for me. I was asking to find out if yours was easier. LMAO.

Every time I ask someone a question on here they get defensive? WTF is the problem with asking questions? And don't you dare tell me my tone because there is no tone....it's text.


I have added support for the preset commands. Simply prefix your text with [P], and the driver will now issue a preset command to the assistant-relay server.

  • [P]wakeup
  • [P]breakfast
  • [P]lunch
  • [P]dinner
  • [P]timetoleave
  • [P]arrivedhome
  • [P]ontheway
  • [P]movietime
  • [P]tvtime
  • [P]bedtime

Here is the updated driver


Thanks again Dan. Just one more question, if I'm correct the driver doesn't send a user name when it issues it's command correct? I know the relay falls back to the default user if not, but if someone were to want to use multiple users so that they could limit certain broadcasts to different devices this might be a good addition?


You're welcome!

Some people are never satisfied... :wink:

I'm not sure what the best method would be to add the username.


I actually was able to "hack together" what I believe will work:

    input(name: "user", type: "string", title:"Username", description: "Enter the username for this device", defaultValue: "", required: false, displayDuringSetup: true)

and then:

 else {
	 myJSON = "{ \"command\": \"${message}\",\"user\": \"${user}\",\"broadcast\": \"true\" }"

I only modified the non prefix commands to see if I could get it to work, according to the console output it seems to be.



Here is your code with the modifications I mentioned on all of the command options, if you feel like tweaking it in anyway and making part of your code please feel free. I have tested all of the command variations and they seem to be working (console output from the assistant relay server is specifying the username correctly).

 *  Google Home Assistant Relay v2
 *  Copyright 2018 Daniel Ogorchock
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *  Change History:
 *    Date        Who            What
 *    ----        ---            ----
 *    2018-12-16  Dan Ogorchock  Original Creation of HUbitat Driver to work with Greg Hesp's Assistant Relay v2
 *    2018-12-18  Dan Ogorchock  Added support for Assistant Relay's PRESETs.  Just add a [P] before the preset you want to use
 *    Credit goes to Greg Hesp's work on the SmartThings platform as a starting point for this very simplified version!
metadata {
	definition (name: "Google Home Assistant Relay v2", namespace: "ogiewon", author: "Dan Ogorchock") {
        capability "Speech Synthesis"
    	capability "Notification"

	preferences {
		input(name: "deviceIP", type: "string", title:"Device IP Address", description: "Enter IP Address of your Assistant Relay Server", required: true, displayDuringSetup: true)
		input(name: "devicePort", type: "string", title:"Device Port", description: "Enter Port of your Assistant Relay Server (defaults to 3000)", defaultValue: "3000", required: true, displayDuringSetup: true)
        input(name: "user", type: "string", title:"Username", description: "Enter the username for this device", defaultValue: "", required: false, displayDuringSetup: true)
		input name: "logEnable", type: "bool", title: "Enable debug logging", defaultValue: true

def logsOff(){
    log.warn "debug logging disabled..."

def parse(String description) {
    //if (logEnable) log.debug "Parsing ${description}"

def speak(message) {
    def myJSON = ""
        message = message.minus("[CC]")
        myJSON = "{ \"command\": \"${message}\",\"user\": \"${user}\" }"
    else if(message.startsWith("[CCC]")){ 
        message = message.minus("[CCC]")
        myJSON = "{ \"command\": \"${message}\",\"user\": \"${user}\",\"converse\": \"true\" }"
    else if(message.startsWith("[P]")){ 
        message = message.minus("[P]")
		myJSON = "{ \"preset\": \"${message}\",\"user\": \"${user}\" }"
     else {
		 myJSON = "{ \"command\": \"${message}\",\"user\": \"${user}\",\"broadcast\": \"true\" }"



def deviceNotification(message) {

def httpPostJSON(myJSON) {
	try {
        if (logEnable) log.debug "Sending ${myJSON} to ${deviceIP}:${devicePort}"

        def headers = [:]
        headers.put("HOST", "${deviceIP}:${devicePort}")
        headers.put("Content-Type", "application/json")
        def method = "POST"
        def path = "/assistant"
        def result = new hubitat.device.HubAction(
            method: method,
            path: path,
            body: myJSON,
            headers: headers
        return result

	} catch (Exception e) {
		log.error "Error = ${e}"

def installed() {

def updated() {
        if (logEnable) runIn(1800,logsOff)