Say-Action in Openhab 3 using JS

In this thread I want to share a script with you that I created to make use the “say” action.
Requirements that I had:

  • reusable function to avoid duplicate code
  • set the volume to a predefined level while saying something and reset it afterwards
  • do not speak if the device is playing music

Prerequisites:

  1. Create a new JS file and place it here: “…/automation/lib/javascript/personal/notifications.js”
(function(context) {
    this.OPENHAB_CONF = (this.OPENHAB_CONF === undefined) ? java.lang.System.getenv("OPENHAB_CONF") : this.OPENHAB_CONF;
	load(OPENHAB_CONF+'/automation/lib/javascript/community/timerMgr.js');
	
    this.logger = (this.logger === undefined) ? Java.type("org.slf4j.LoggerFactory").getLogger("org.openhab.model.script.Rules.notifications") : this.logger; 
    this.voice = (this.voice === undefined) ? Java.type("org.openhab.core.model.script.actions.Voice") : this.voice; 
    this.tm = (this.tm === undefined) ? new TimerMgr() : this.tm;
    
    context.say = function(tts,duration) {
    	//Get current volume
    	var volumeLR = context.items["GHLivingRoom_Volume"];
    	var volumeOF = context.items["GHOffice_Volume"];
    	
    	
    	if(context.items["GHLivingRoom_Control"] == PAUSE){
    		context.events.sendCommand("GHLivingRoom_Volume", 40);
    		this.voice.say(tts, "googletts:deDEWavenetC", "chromecast:chromecast:2ae2e226dd29fad4d20afc65e4bc4061")
    		this.tm.check("notificationSay", duration,
                      function() { context.events.sendCommand("GHLivingRoom_Volume", volumeLR); });
    	
    	}
    	else if(context.items["GHOffice_Control"] == PAUSE){
    		context.events.sendCommand("GHOffice_Volume", 40);
    		this.voice.say(tts, "googletts:deDEWavenetC", "chromecast:chromecast:38a71a03c5265c00036a43e0fb39b7b5")
    		this.tm.check("notificationSay", duration,
                      function() { context.events.sendCommand("GHOffice_Volume", volumeOF); });
    	}
  	}   
})(this)
  1. Create a new rule in MainUI and select “execute a given script” --> ECMA
this.OPENHAB_CONF = (this.OPENHAB_CONF === undefined) ? java.lang.System.getenv("OPENHAB_CONF") : this.OPENHAB_CONF;
load(this.OPENHAB_CONF+'/automation/lib/javascript/personal/notifications.js');

say("Hello","1s");

I hope it helps you!
If there is anything that can be improved, please let me know.

Is that a use of TimerMgr I see in the wild?

:partying_face:

Note, I recently fixed a bug in the cancelAll() function. It was named canceAll(). :confounded:

Great tutorial, thanks for posting! I’m going to move it to the Solutions subcategory.

If you have any need to delay and queue up commands to say (I don’t remember if it returns immediately or blocks until it’s done) I plan on porting over my Gatekeeper implementation to JS too. But the Getting Started tutorial has taken priority right now.

Since you are using OH3, the play and say actions can adjust the volume on their own…

Also, your library should go somewhere other that in the $OPENHAB_CONF/automation/jsr223/ directory, which is intended for scripts. This directory is hard coded into the rule engine. I proposed changing this, but my request has been ignored. I suggest putting personal libraries in $OPENHAB_CONF/automation/lib/javascript/personal/

There is also an actions.js in the helper libraries to make it easier to get to actions.

Yes it is! Thanks for contributing, it helps a lot.

If you have any need to delay and queue up commands to say

This enhancement is planned for the future. I will have a look into the Gatekeeper :slight_smile:

Thanks for pointing to this option. I have tried this functionality already, but it does not meet my usecase. I may have done something wrong. When this parameter is used, the volume is set to the defined level and reset immediately.
If the text is e.g. “Hello World how are you?”, just the “Hello” is spoken with the defined level, but not the rest of the text.

I suggest putting personal libraries in $OPENHAB_CONF/automation/lib/javascript/personal/…

I will change that in the initial post.

I don’t have the JS version of it posted yet but I’ll try to get it posted this weekend. There’s a Python version though which shows how it’ll work.

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.