[UPDATED] - Message Central - Make your home speak

No, message priority is a feature of the Pushover official API. The assistant-relay Driver is really just used to broadcast TTS on all Google Home devices in your house.

1 Like

That makes things a little easier.

A few less lines of code to add to each trigger.

Ok, Mark Iā€™ll have a look at this in the morning

Andy

I would think you should just implement a generic ā€˜Speech Synthesisā€™ device option, not something specific to the Google Assistant-Relay driver.

Yep, thatā€™s what I was thinking and was the reason for the questions.

Andy

3 Likes

OK
I have completed a major recode to allow options for Speech Synthesis
I have not had a chance to try all the options but try this and please let me know if you find any bugs etc.

Updated child app: Version 11.0.0

One thing to note:
For anyone who has been using this with the 'musicPlayer' capability
You will need to open each child and select "Voice Message (MusicPlayer)" as the old "Voice Message" is no longer valid.
Once selected the previous settings should reappear so you can then just save the child again.

Andy

2 Likes

I have also added a number of 'weather' variables.
The following variables have been added:

%wsum% - Replaced with a weather summary
%high% - Replaced with a 'Forecast High'
%low% - Replaced with a 'Forecast Low
%hum% - Replaced with a 'Humidity'
%wnow% - Replaced with 'Weather Now'
%rain% - Replaced with 'Chance of Rain'
%vis% - Replaced with 'Visibility'
%wgust% - Replaced with 'Wind Gust'
%wspeed% - Replaced with 'Wind Speed'
%wdir% - Replaced with 'Wind Direction'
%feel% - Replaced with 'FeelsLike'
%temp% - Replaced with 'Temperature'

You will need the appropriate 'weather device' for these to work.

something like this:

or this:

or this:

https://github.com/CobraVmax/Hubitat/tree/master/Drivers/Weather

As an example, here is the message I use for a daily weather (using the weewx driver)

%greeting% , Here is your weather for today,,, %wnow%,, With a high of %high% degrees ,, and a low of %low% degrees. , Temperature is currently, %temp% degrees. and it feels like %feel% . Humidity is currently, %hum% % . Wind, is from the %wdir% at %wspeed% mph, with gusts up to %wgust%. Visibility is around %vis% miles. , and,, There is a %rain% % chance of rain today

You might notice I use a comma (,) as a slight pause at various times

Andy

1 Like

Thanks for this Andy! Tested with @ogiewon Google Assistant Relay, works perfectly.

2 Likes

Great! :slight_smile:

I am giving this another try. I think you need to add an 'if' to the begining of line 2291 of the child app.

if(state.msgType == "Voice Message (SpeechSynth)"){
    if(state.talkpresence == 'present' && state.msg1 != null){
   def msg = message1     
   compileMsg(msg)    
   LOGDEBUG("Presence - Speech Synth Message - Sending Message: $msg")     
        }
     (state.talkpresence == 'not present' && state.msg2 != null){
     def msg = message2     
   compileMsg(msg)    
    LOGDEBUG("Presence - Speech Synth Message - Sending Message: $msg")   
    speechSynthNow(state.fullPhrase)  
     }  
 }      

so that

(state.talkpresence == 'not present' && state.msg2 != null){

is

if (state.talkpresence == 'not present' && state.msg2 != null){

Thanks.

@Matthew
You are correct.
Obviously when I was copy/pasting I must have missed the ā€˜ifā€™ :slight_smile:
Iā€™ll get it corrected in the morning and check the rest of the code for other missing bits :slight_smile:

Thanks for the catch.

Andy

What started as a fairly basic alternative to BT has become a bit of a beast!

Andy

1 Like

It happens quickly! Those feature requests start rolling in and then bam, you're spending a lot of time adding code, debugging, publishing, correcting, streamlining, so on and so forth. One seemingly small idea turns into another and another. I've enjoyed developing BT and conversing with all of the users. It has been an awesome (and time demanding) experience. Good job on your project, it seems many users are happy with your work!

2 Likes

I wanted to use variables within the %group#% random message groups (e.g. %device%; %greeting%; %time%; etc...). It didn't work and just spoke the variable name instead of it's intended content. When I looked at the code it appears it may be able to easily allow this be reordering a few lines of code here:

def msgComp = ""
msgComp = msg.toUpperCase()
LOGDEBUG("msgComp = $msgComp")
if (msgComp.contains("%WNOW%")) {msgComp = msgComp.toUpperCase().replace('%WNOW%', state.weatherNow )}
if (msgComp.contains("%RAIN%")) {msgComp = msgComp.toUpperCase().replace('%RAIN%', state.weatherChanceOfRain )}
if (msgComp.contains("%VIS%")) {msgComp = msgComp.toUpperCase().replace('%VIS%', state.weatherVisibility )}
if (msgComp.contains("%WGUST%")) {msgComp = msgComp.toUpperCase().replace('%WGUST%', state.weatherWindGust )}
if (msgComp.contains("%WSPEED%")) {msgComp = msgComp.toUpperCase().replace('%WSPEED%', state.weatherWindSpeed )}
if (msgComp.contains("%WDIR%")) {msgComp = msgComp.toUpperCase().replace('%WDIR%', state.weatherWindDir )}
if (msgComp.contains("%FEEL%")) {msgComp = msgComp.toUpperCase().replace('%FEEL%', state.weatherFeelsLike )}
if (msgComp.contains("%TEMP%")) {msgComp = msgComp.toUpperCase().replace('%TEMP%', state.weatherTemperature )}
if (msgComp.contains("%HUM%")) {msgComp = msgComp.toUpperCase().replace('%HUM%', state.weatherHumidity )}
if (msgComp.contains("%LOW%")) {msgComp = msgComp.toUpperCase().replace('%LOW%', state.weatherForecastLow )}
if (msgComp.contains("%HIGH%")) {msgComp = msgComp.toUpperCase().replace('%HIGH%', state.weatherForecastHigh )} 
if (msgComp.contains("%WSUM%")) {msgComp = msgComp.toUpperCase().replace('%WSUM%', state.weatherSummary )} 
if (msgComp.contains("%GROUP1%")) {msgComp = msgComp.toUpperCase().replace('%GROUP1%', getPre() )}
if (msgComp.contains("%GROUP2%")) {msgComp = msgComp.toUpperCase().replace('%GROUP2%', getPost() )}
if (msgComp.contains("%GROUP3%")) {msgComp = msgComp.toUpperCase().replace('%GROUP3%', getWakeUp() )}
if (msgComp.contains("%TIME%")) {msgComp = msgComp.toUpperCase().replace('%TIME%', getTime(false,true))}  
if (msgComp.contains(":")) {msgComp = msgComp.toUpperCase().replace(':', ' ')}
if (msgComp.contains("%DAY%")) {msgComp = msgComp.toUpperCase().replace('%DAY%', getDay() )}  
if (msgComp.contains("%DATE%")) {msgComp = msgComp.toUpperCase().replace('%DATE%', getdate() )}  
if (msgComp.contains("%YEAR%")) {msgComp = msgComp.toUpperCase().replace('%YEAR%', getyear() )}  
if (msgComp.contains("%OPENCONTACT%")) {msgComp = msgComp.toUpperCase().replace('%OPENCONTACT%', getContactReportOpen() )}  
if (msgComp.contains("%CLOSEDCONTACT%")) {msgComp = msgComp.toUpperCase().replace('%CLOSEDCONTACT%', getContactReportClosed() )} 
if (msgComp.contains("%DEVICE%")) {msgComp = msgComp.toUpperCase().replace('%DEVICE%', getNameofDevice() )}  
if (msgComp.contains("%EVENT%")) {msgComp = msgComp.toUpperCase().replace('%EVENT%', getWhatHappened() )}  
if (msgComp.contains("%GREETING%")) {msgComp = msgComp.toUpperCase().replace('%GREETING%', getGreeting() )}      
if (msgComp.contains("N/A")) {msgComp = msgComp.toUpperCase().replace('N/A', ' ' )}
if (msgComp.contains("NO STATION DATA")) {msgComp = msgComp.toUpperCase().replace('NO STATION DATA', ' ' )}

convertWeatherMessage(msgComp)

}

I moved the %group1%, %group2% and %group3% up so there were before the other variables, but after the weather variables. That way when once of the %group% variables returns a string with another variable within it, that variable will be be replaced by the subsequent command.

I have not been able to test it yet .... but I think this should work.

1 Like

You are SO right.
I was using your original BT on smarttings but wanted something a bit simpler for my own use.

I was looking at the post of my original release on ST

"If you find that there is something missing that would be useful to people then please let me know and I might be able to include it.
BUTā€¦ please bear in mind that I want to keep this simple, uncomplicated, and easy to use."

What started as a few hundred lines of code has now gone to almost 3.5K !
I know it still doesn't compare to the amount of work you have done on BT (or the amount of code) but as I said, it has become a bit of a beast

I even remember posting once that, although I thought your idea of random pre/post messages was fantastic, I would never add it to MC :slight_smile:

And here we are.. now discussing the order to add variables to the random group messages. :slight_smile:

Andy

1 Like

@Matthew
I had not tested it before so was unaware of the outcome.
You are correct, this should work.
However, this means that you would not be able to include any of the weather attributes in the groups.
I have just tested using the %WNOW% variable is a group (after putting the groups at the top ABOVE the weather variables) and it seems to work ok.
I think moving them to be the first variable would be sensible.

def msgComp = ""
    msgComp = msg.toUpperCase()
    LOGDEBUG("msgComp = $msgComp")
    if (msgComp.contains("%GROUP1%")) {msgComp = msgComp.toUpperCase().replace('%GROUP1%', getPre() )}
    if (msgComp.contains("%GROUP2%")) {msgComp = msgComp.toUpperCase().replace('%GROUP2%', getPost() )}
    if (msgComp.contains("%GROUP3%")) {msgComp = msgComp.toUpperCase().replace('%GROUP3%', getWakeUp() )}
    if (msgComp.contains("%WNOW%")) {msgComp = msgComp.toUpperCase().replace('%WNOW%', state.weatherNow )}
    if (msgComp.contains("%RAIN%")) {msgComp = msgComp.toUpperCase().replace('%RAIN%', state.weatherChanceOfRain )}
    if (msgComp.contains("%VIS%")) {msgComp = msgComp.toUpperCase().replace('%VIS%', state.weatherVisibility )}
    if (msgComp.contains("%WGUST%")) {msgComp = msgComp.toUpperCase().replace('%WGUST%', state.weatherWindGust )}
    if (msgComp.contains("%WSPEED%")) {msgComp = msgComp.toUpperCase().replace('%WSPEED%', state.weatherWindSpeed )}
    if (msgComp.contains("%WDIR%")) {msgComp = msgComp.toUpperCase().replace('%WDIR%', state.weatherWindDir )}
    if (msgComp.contains("%FEEL%")) {msgComp = msgComp.toUpperCase().replace('%FEEL%', state.weatherFeelsLike )}
    if (msgComp.contains("%TEMP%")) {msgComp = msgComp.toUpperCase().replace('%TEMP%', state.weatherTemperature )}
    if (msgComp.contains("%HUM%")) {msgComp = msgComp.toUpperCase().replace('%HUM%', state.weatherHumidity )}
    if (msgComp.contains("%LOW%")) {msgComp = msgComp.toUpperCase().replace('%LOW%', state.weatherForecastLow )}
    if (msgComp.contains("%HIGH%")) {msgComp = msgComp.toUpperCase().replace('%HIGH%', state.weatherForecastHigh )} 
    if (msgComp.contains("%WSUM%")) {msgComp = msgComp.toUpperCase().replace('%WSUM%', state.weatherSummary )} 
    if (msgComp.contains("%TIME%")) {msgComp = msgComp.toUpperCase().replace('%TIME%', getTime(false,true))}  
    if (msgComp.contains(":")) {msgComp = msgComp.toUpperCase().replace(':', ' ')}
    if (msgComp.contains("%DAY%")) {msgComp = msgComp.toUpperCase().replace('%DAY%', getDay() )}  
	if (msgComp.contains("%DATE%")) {msgComp = msgComp.toUpperCase().replace('%DATE%', getdate() )}  
    if (msgComp.contains("%YEAR%")) {msgComp = msgComp.toUpperCase().replace('%YEAR%', getyear() )}  
 	if (msgComp.contains("%OPENCONTACT%")) {msgComp = msgComp.toUpperCase().replace('%OPENCONTACT%', getContactReportOpen() )}  
    if (msgComp.contains("%CLOSEDCONTACT%")) {msgComp = msgComp.toUpperCase().replace('%CLOSEDCONTACT%', getContactReportClosed() )} 
	if (msgComp.contains("%DEVICE%")) {msgComp = msgComp.toUpperCase().replace('%DEVICE%', getNameofDevice() )}  
	if (msgComp.contains("%EVENT%")) {msgComp = msgComp.toUpperCase().replace('%EVENT%', getWhatHappened() )}  
    if (msgComp.contains("%GREETING%")) {msgComp = msgComp.toUpperCase().replace('%GREETING%', getGreeting() )}      
    if (msgComp.contains("N/A")) {msgComp = msgComp.toUpperCase().replace('N/A', ' ' )}
	if (msgComp.contains("NO STATION DATA")) {msgComp = msgComp.toUpperCase().replace('NO STATION DATA', ' ' )}

That way, ANY variable used in a '%group#% should work.
Have a play, and if it works for you then I'll amend the code on GitHub

Andy

1 Like

No one has come or gone, so I still have not been able to test this. I did move the 'group's to the top as you suggested.

Since we are discussing the random messages and the order of them, why not make it even more complicated, or user friendly I mean :innocent:? I know I am most likely an outlier here, but what about either increasing the number of options available in the groups, or better, making that a user selectable number? (I know you don't get enough sleep as it is now :grin:) Right now I increased the options from 5 to 25 in Group 1 & 2 and from 5 to 10 in Group 3. Since it picks a random option you should not have a blank option so you do not want more options than you plan on using. I was thinking let the user specify how many they want and then dynamically make those available in a ' for loop'. I will play with that (if I get the time :grin:) and see what I can come up with.

1 Like

You can always create a virtual presence - That's what I always use for testing.

Andy

1 Like

Thanks. I had not thought of that. That should speed up testing significantly.

1 Like

Some updates:

You need to add the .toUpperCase() to all the lines in the Complie(msg) routine because it is pulling in the random messages, or other variables where they may be lower case. Like this:

> private compileMsg(msg) {
>     
> 	LOGDEBUG("compileMsg - msg = ${msg}")
>     
>     if(weather1){
>         weather1.poll()
>         runIn(10, waitabit)
>     }
>     
>     def msgComp = ""
>     msgComp = msg.toUpperCase()
>     LOGDEBUG("BEFORE msgComp = $msgComp")
>     if (msgComp.toUpperCase().contains("%GROUP1%")) {msgComp = msgComp.toUpperCase().replace('%GROUP1%', getPre() )}
>     if (msgComp.toUpperCase().contains("%GROUP2%")) {msgComp = msgComp.toUpperCase().replace('%GROUP2%', getPost() )}
>     if (msgComp.toUpperCase().contains("%GROUP3%")) {msgComp = msgComp.toUpperCase().replace('%GROUP3%', getWakeUp() )}
>     if (msgComp.toUpperCase().contains("%WNOW%")) {msgComp = msgComp.toUpperCase().replace('%WNOW%', state.weatherNow )}
>     if (msgComp.toUpperCase().contains("%RAIN%")) {msgComp = msgComp.toUpperCase().replace('%RAIN%', state.weatherChanceOfRain )}
>     if (msgComp.toUpperCase().contains("%VIS%")) {msgComp = msgComp.toUpperCase().replace('%VIS%', state.weatherVisibility )}
>     if (msgComp.toUpperCase().contains("%WGUST%")) {msgComp = msgComp.toUpperCase().replace('%WGUST%', state.weatherWindGust )}
>     if (msgComp.toUpperCase().contains("%WSPEED%")) {msgComp = msgComp.toUpperCase().replace('%WSPEED%', state.weatherWindSpeed )}
>     if (msgComp.toUpperCase().contains("%WDIR%")) {msgComp = msgComp.toUpperCase().replace('%WDIR%', state.weatherWindDir )}
>     if (msgComp.toUpperCase().contains("%FEEL%")) {msgComp = msgComp.toUpperCase().replace('%FEEL%', state.weatherFeelsLike )}
>     if (msgComp.toUpperCase().contains("%TEMP%")) {msgComp = msgComp.toUpperCase().replace('%TEMP%', state.weatherTemperature )}
>     if (msgComp.toUpperCase().contains("%HUM%")) {msgComp = msgComp.toUpperCase().replace('%HUM%', state.weatherHumidity )}
>     if (msgComp.toUpperCase().contains("%LOW%")) {msgComp = msgComp.toUpperCase().replace('%LOW%', state.weatherForecastLow )}
>     if (msgComp.toUpperCase().contains("%HIGH%")) {msgComp = msgComp.toUpperCase().replace('%HIGH%', state.weatherForecastHigh )} 
>     if (msgComp.toUpperCase().contains("%WSUM%")) {msgComp = msgComp.toUpperCase().replace('%WSUM%', state.weatherSummary )} 
>     if (msgComp.toUpperCase().contains("%TIME%")) {msgComp = msgComp.toUpperCase().replace('%TIME%', getTime(false,true))}  
>     if (msgComp.toUpperCase().contains(":")) {msgComp = msgComp.toUpperCase().replace(':', ' ')}
>     if (msgComp.toUpperCase().contains("%DAY%")) {msgComp = msgComp.toUpperCase().replace('%DAY%', getDay() )}  
> 	if (msgComp.toUpperCase().contains("%DATE%")) {msgComp = msgComp.toUpperCase().replace('%DATE%', getdate() )}  
>     if (msgComp.toUpperCase().contains("%YEAR%")) {msgComp = msgComp.toUpperCase().replace('%YEAR%', getyear() )}  
>  	if (msgComp.toUpperCase().contains("%OPENCONTACT%")) {msgComp = msgComp.toUpperCase().replace('%OPENCONTACT%', getContactReportOpen() )}  
>     if (msgComp.toUpperCase().contains("%CLOSEDCONTACT%")) {msgComp = msgComp.toUpperCase().replace('%CLOSEDCONTACT%', getContactReportClosed() )} 
> 	if (msgComp.toUpperCase().contains("%DEVICE%")) {msgComp = msgComp.toUpperCase().replace('%DEVICE%', getNameofDevice() )}  
> 	if (msgComp.toUpperCase().contains("%EVENT%")) {msgComp = msgComp.toUpperCase().replace('%EVENT%', getWhatHappened() )}  
>     if (msgComp.toUpperCase().contains("%GREETING%")) {msgComp = msgComp.toUpperCase().replace('%GREETING%', getGreeting() )}      
> 	if (msgComp.toUpperCase().contains("N/A")) {msgComp = msgComp.toUpperCase().replace('N/A', ' ' )}
> 	if (msgComp.toUpperCase().contains("NO STATION DATA")) {msgComp = msgComp.toUpperCase().replace('NO STATION DATA', ' ' )}
>     LOGDEBUG("AFTER msgComp = $msgComp")
>     convertWeatherMessage(msgComp)
>     LOGDEBUG("state.fullPhrase = '$state.fullPhrase'")
> }

In this section:

  if(state.msgType == "Voice Message (SpeechSynth)"){
    if(state.talkpresence == 'present' && state.msg1 != null){
	   def msg = message1     
   		compileMsg(msg)    
	   LOGDEBUG("Presence - Speech Synth Message - Sending Message: $msg")     
    }
    if(state.talkpresence == 'not present' && state.msg2 != null){
     	def msg = message2     
   	compileMsg(msg)    
    	LOGDEBUG("Presence - Speech Synth Message - Sending Message: $msg")   
     speechSynthNow(state.fullPhrase)        
     }  
 }      

It was not 'speaking' my arrivals, only my departures. You need to move the ''speechSynthNow' on the other side of the close bracket for the 'if' statement, or add an additional ''speechSynthNow' to the bottom of the ''if' stated that proceeds this one.

With those changes it is working pretty well. Testing continues......

@Matthew
Hmmm...
msgComp = msg.toUpperCase() should set all the data to uppercase..

Ah! I see what you mean it may not convert the contents of the group .

Thanks for catching the other bug with the speechsynth
I'll get that sorted now

Andy

1 Like