[UPDATED] - Message Central - Make your home speak

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

Version 11.1.0 Uploaded with various fixes :slight_smile:
Apart for the speechSynth issue and the nesting of the variables
I have also fixed the 'timeOfDayIsBetween' method call so you can now use the time restrictions correctly (hopefully) :slight_smile:

Andy

1 Like

@Matthew
Thank you very much for your donation
It really isn't necessary but always welcome :slight_smile:

Andy

@Cobra Andy, in theory I should be able to use the speech synthesis method to send a notification to more than one device at a time correct? The app allows me to select multiple devices but it didn't seem to work for me when I tried it.

I haven't tried it with the latest version though.

Thanks

@halfrican.ak
Mark
There was an issue with the speechsynth before the latest update.
You should be able to select more than one device and send the message to all selected.

Please let me know if you have problems.

Andy

Sounds good, I'll try it again and let you know if it doesn't work. Thanks again.

How did you come up with 60 random messages? !!

I struggle to get 15 :slight_smile:

Andy

BTW
What triger are you using?

Andy

I am replicating a webCoRE pitson I had been using to announce arrivals/departures. I have 25 'Arrival' greetings and 25 'Departure' sayings.

Here they are if you want them (some are phonetic spelling because the englsh doesn't work so well):

def prePostPage1() {
dynamicPage(name: "prePostPage1") {

section() {
input "preMsg01", "text", title: " %group1% - message 01", required: false, defaultValue: "Welcome home %device%."
input "preMsg02", "text", title: " %group1% - message 02", required: false, defaultValue: "How you doing %device%?"
input "preMsg03", "text", title: " %group1% - message 03", required: false, defaultValue: "What's up %device%?"
input "preMsg04", "text", title: " %group1% - message 04", required: false, defaultValue: "Long time no see %device%."
input "preMsg05", "text", title: " %group1% - message 05", required: false, defaultValue: "Hey %device%."
input "preMsg06", "text", title: " %group1% - message 06", required: false, defaultValue: "Nice you see you %device%."
input "preMsg07", "text", title: " %group1% - message 07", required: false, defaultValue: "Look who's home, it's %device%."
input "preMsg08", "text", title: " %group1% - message 08", required: false, defaultValue: "Nice to have you back %device%."
input "preMsg09", "text", title: " %group1% - message 09", required: false, defaultValue: "Howdy do %device%."
input "preMsg10", "text", title: " %group1% - message 10", required: false, defaultValue: "What's going on %device%?"
input "preMsg11", "text", title: " %group1% - message 11", required: false, defaultValue: "How is everything $device%?"
input "preMsg12", "text", title: " %group1% - message 12", required: false, defaultValue: "It's been ages since I have seen you %device%."
input "preMsg13", "text", title: " %group1% - message 13", required: false, defaultValue: "Where have you been hiding %device%?"
input "preMsg14", "text", title: " %group1% - message 14", required: false, defaultValue: "How's it hanging %device?"
input "preMsg15", "text", title: " %group1% - message 15", required: false, defaultValue: "What's cookin %device%?"
input "preMsg16", "text", title: " %group1% - message 16", required: false, defaultValue: "What's shakin $device%?"
input "preMsg17", "text", title: " %group1% - message 17", required: false, defaultValue: "Greetings and salutations %device%."
input "preMsg18", "text", title: " %group1% - message 18", required: false, defaultValue: "Aloha %device%."
input "preMsg19", "text", title: " %group1% - message 19", required: false, defaultValue: "Shalom %device%."
input "preMsg20", "text", title: " %group1% - message 20", required: false, defaultValue: "How goes it %device%?"
input "preMsg21", "text", title: " %group1% - message 21", required: false, defaultValue: "What's happening %device%"
input "preMsg22", "text", title: " %group1% - message 22", required: false, defaultValue: "How goes it %device%?"
input "preMsg23", "text", title: " %group1% - message 23", required: false, defaultValue: "Roll out the red carpet for %device%!"
input "preMsg24", "text", title: " %group1% - message 24", required: false, defaultValue: "%greeting% %device%."
input "preMsg25", "text", title: " %group1% - message 25", required: false, defaultValue: "OHlah %device%."
}
}
}

def prePostPage2() {
dynamicPage(name: "prePostPage2") {

section() {
input "postMsg01", "text", title: " %group2% - message 01", required: false, defaultValue: "Goodbye %device%. Hope you have a %greeting%."
input "postMsg02", "text", title: " %group2% - message 02", required: false, defaultValue: "See you later %device%."
input "postMsg03", "text", title: " %group2% - message 03", required: false, defaultValue: "Live long and prosper %device%."
input "postMsg04", "text", title: " %group2% - message 04", required: false, defaultValue: "Farewell %device%"
input "postMsg05", "text", title: " %group2% - message 05", required: false, defaultValue: "Hope you have a great time %device%."
input "postMsg06", "text", title: " %group2% - message 06", required: false, defaultValue: "Take care %device%."
input "postMsg07", "text", title: " %group2% - message 07", required: false, defaultValue: "Smell you later %device%."
input "postMsg08", "text", title: " %group2% - message 08", required: false, defaultValue: "I never thought %device% would leave!"
input "postMsg09", "text", title: " %group2% - message 09", required: false, defaultValue: "ahTHYOHS %device%"
input "postMsg10", "text", title: " %group2% - message 10", required: false, defaultValue: "Chow %device%."
input "postMsg11", "text", title: " %group2% - message 11", required: false, defaultValue: "Oh revwahr %device%."
input "postMsg12", "text", title: " %group2% - message 12", required: false, defaultValue: "Sighenara %device%."
input "postMsg13", "text", title: " %group2% - message 13", required: false, defaultValue: "Tah Tah for now %device%."
input "postMsg14", "text", title: " %group2% - message 14", required: false, defaultValue: "Catch you later %device%."
input "postMsg15", "text", title: " %group2% - message 15", required: false, defaultValue: "To-da-loo %device%."
input "postMsg16", "text", title: " %group2% - message 16", required: false, defaultValue: "See you in the funny papers %device%."
input "postMsg17", "text", title: " %group2% - message 17", required: false, defaultValue: "Toodles &device%."
input "postMsg18", "text", title: " %group2% - message 18", required: false, defaultValue: "Godspeed %device%."
input "postMsg19", "text", title: " %group2% - message 19", required: false, defaultValue: "So long %device%."
input "postMsg20", "text", title: " %group2% - message 20", required: false, defaultValue: "Oufveeduhrzeyuhn %devixce%."
input "postMsg21", "text", title: " %group2% - message 21", required: false, defaultValue: "Aloha %device%"
input "postMsg22", "text", title: " %group2% - message 22", required: false, defaultValue: "Shalom %device%"
input "postMsg23", "text", title: " %group2% - message 23", required: false, defaultValue: "Cheerio %device%"
input "postMsg24", "text", title: " %group2% - message 24", required: false, defaultValue: "AhrreevehDEHRtchee %device%"
input "postMsg25", "text", title: " %group2% - message 25", required: false, defaultValue: "Bye %device%. Hope you have a %greeting%."

}
}
}

One thing I have noticed is that she says 'it' as "Eye TEE" (as in Information Technologies) instead of the word 'it'? I thought it was because of the capitalization, but I converted the final phrase to lowercase and she still says 'I.T.' I'll have to either not use 'it' or find a way that she can pronounce it correctly.

UPDATE: I changed 'it' to 'ette' and it sounds pretty close now. At least it is far better then 'EYE TEE'.

I was noticing the issue with the presence trigger speicifcally

Thanks

1 Like

Yep!
That’s the trigger that had the major problem
Should be sorted now though. :slight_smile:

Andy