Enable/Disable Alexa Voice Control

Hi all,

i included an Amazon Echo with voicecontrol by Alexa within openHAB (2.4) and everything works fine.
Is there a way to enable/disable Alexa from openHAB (e.g. within a rule)? The reason for that is, that I want to disable the openHAB control by Alexa when I am leaving the house, so that no one from outside can control my home by shouting from outside.

Many thanks,

Thorsten

If you have presents detection, so that OH knows when your home/away, you can try using that as a condition (the if part in a rule) to check before Alexa send a command.

@Chumbos I donā€™t think there is an easy way to accomplish that at the moment on the software side. It would be nice if Amazon would provide a way to programmatically mute echo devices. The only solution I can see is to use a smart plug/outlet with your echo device that you could setup to turn off when you leave the house.

Thanks @H102 - if i got i right, this would mean that i would need to check in every rule for items i can control via Alexa if this condition is true and i could not control those item via my App if i am not at home.

Yes, a programmable way to mute the echo device would be a good solution. I setup a Homematic IP installation for a friend and if you turn the ā€œalarmā€ mode on in the App the Alexa voice control is disabled until the alarm mode is switched off again. I am wondering how they have done it.

Maybe there is the chance to add this feature in the openHAB Alexa binding as an idea.

I will try the workaround with the smart plug in the meantime. :slight_smile:

Sort of. See Design Pattern: Separation of Behaviors for a way to centralize the check so it only needs to appear in one place.

2 Likes

It would be nice if there was a channel to switch off the Voice, like a channel that links to the Mute button.

1 Like

I too am looking for a way to mute alexa from within a rule (mute does not seem like the right word to stop something listening?? ).
I have an "Away Mode " rule that locks doors and alarms an alarm. I often turn this on by asking Alexa to do so. As I have two echos located outside, if someone knew the magic words, they could turn this mode off and effectively disable all security.
Fortunately, security is not too much of an issue where I live, but it would be nice to disable voice commands when this mode is on.

Iā€™m also looking for a way to disable Alexa voice commands via rule so that incoming commands from Amazon will be ignored on OH3 side. Same usecase like the poster before: out of house and donā€™t allow commands coming from the outside. Since item commands are not triggered by rules on my system, but are managed by the Alexa Skill binding, there is no way to ā€œinterceptā€ those with a check in a rule.

Is it somehow possible to stop the Alexa Skill binding or so via REST? Thanks to JRule I guess I would also have full access to the OH Java API if needed. Maybe someone already did something like this.

There is a way. Assuming OH 3 and UI created rules, create a Switch Item. When this Item is ON the commands from Alexa are allowed. When itā€™s off they are to be ignored.

Next create a Proxy Item for Alexa to command.

Then, create a rule that gets triggered when the Proxy Item is commanded that forwards that command to the ā€œrealā€ Item.

Finally, create a rule that triggers when the Switch Item from above changes. When it turns OFF, disable the rule that forwards the proxy commands to the ā€œrealā€ Item. When it turns ON enable the rule.

That essentially cuts off the commands from Alexa.

Use a Group and Design Pattern: Associated Items in the Proxy Item naming and you can create the rule that forwards the commands from Alexa in one rule.

Interesting. Iā€™ve got my rules in files. But doesnā€™t that mean I have to create proxy items for all of my 300+ items and expose them instead to the Alexa Skill than the real ones :)?

In that case put and if(AlexaCommands.state == OFF) { return; } at the top of those rules.

Or create the rule in the UI, query for the rule in the REST API Explorer, and then save that JSON to a .json file in $OH_CONF/automation.

Or just leave it defined in the UI.

Unfortunately Rules DSL does not support enabling and disabling other rules.

Yes, or more likely create new ā€œrealā€ Items and move the links to the Channels to those instead of the already exposed Alexa Items. That limits the risk of disrupting the connection with Alexa.

Iā€™m not claiming that itā€™s a perfect solution and that it wonā€™t take some work. But it is a solution that can be employed. Note that this approach is generic and will work with any sort of integration, not just Alexa.

Ok got it :). Thanks for sharing this approach!

Hi, I see that there were no updates here for a long time. Had something changed in the possibilities? It would be really the easiest way, then the binding would offer a channel for it. Thank you for an update

I have been using an Echo outside for 3 years now, same Echo Dot v1, this entire time.

Hereā€™s how I handle the different scenarioā€™s:

  1. When leaving the house or at night, I set volumes to zero.
                    var EchoThing = getThingStatusInfo("amazonechocontrol:account:account1")
					if ((EchoThing !== null) && (EchoThing.getStatus().toString() == 'ONLINE')) {
					
						logInfo("ECHO","Alexa Outside Volume set to 0.") 
						createTimer(now().plusSeconds(5), [ | Echo_BackYard_Volume.sendCommand('0') ])
							Thread::sleep(2000)
						createTimer(now().plusSeconds(5), [ | Echo_BackYard_textToSpeechVolume.sendCommand('0') ])
							Thread::sleep(2000)	
						Echo_BackYard_doNotDisturb.sendCommand(ON)	
					}
  1. Amazon likes to change volumes sometimes (not sure when/why):
rule "Echo BackYard Volume Changed by Amazon"
	when
		Item Echo_BackYard_Volume changed
	then

		var EchoThingBackYard = getThingStatusInfo("amazonechocontrol:echo:account1:echobackyard")
		if ((systemStarted.state != ON && EchoThingBackYard !== null) && (Alexa_Status.state == 'ONLINE' && gInternet.state == ON && Echo_BackYard_Volume.state > 0 && Echo_BackYard_Volume.state <= 30)) {

			logInfo("ECHO","Setting Echo_BackYard_Volume to 0 since its set under 30.")
			logInfo("ECHO","Prior Echo_BackYard_Volume set to " + Echo_BackYard_Volume.state)
			createTimer(now().plusSeconds(5), [ | Echo_BackYard_Volume.sendCommand('0') ])
				Thread::sleep(2000)
			createTimer(now().plusSeconds(5), [ | Echo_BackYard_textToSpeechVolume.sendCommand('0') ])	
				Thread::sleep(2000)	
			createTimer(now().plusSeconds(5), [ | Echo_BackYard_doNotDisturb.sendCommand(ON) ])				
			logInfo("ECHO","After Echo_BackYard_Volume set to " + Echo_BackYard_Volume.state)
		} 
end
  1. When the Echo device is used, it sends an email and takes a picture of who is in the back yard. If the house alarm system is ON or itā€™s past X hours at night, then I call an Alexa routine that kills whatever is asked of it.

Echo_BackYard_StartRoutine.sendCommand(ā€˜kill use backyard echoā€™)

rule "Echo BackYard Last Command Heard Audit"
	when
		Item Echo_BackYard_LastVoiceCommand changed
	then

		var EchoThingBackYard = getThingStatusInfo("amazonechocontrol:echo:account1:echobackyard")
		if ((systemStarted.state != ON && EchoThingBackYard !== null) && (Alexa_Status.state == 'ONLINE' && gInternet.state == ON)) {

			if (Echo_BackYard_LastVoiceCommand.state.toString() == 'amazon' && PatioDoor_Status.state != OPEN && gPart1Zone3Fault.state != ON && (currHour.state >= 22 || currHour.state <= 6)) {

				logInfo("ECHO","Prior Echo_BackYard_Volume set to " + Echo_BackYard_Volume.state)

				Echo_BackYard_StartRoutine.sendCommand('kill use backyard echo')
					Thread::sleep(1500)

				logInfo("ECHO","After Echo_BackYard_Volume set to " + Echo_BackYard_Volume.state)
				logInfo("ECHO","Echo_BackYard_StartRoutine --> kill use backyard echo <-- executed.")
				return;
			} 

			if (gInternet.state == ON && (Echo_BackYard_LastVoiceCommand.state.toString() == 'amazon' || Echo_BackYard_LastVoiceCommand.state === null || Echo_BackYard_LastVoiceCommand.state == NULL)) { return; }

			if (gInternet.state == ON && gPort25.state == ON && PatioDoor_Status.state != OPEN && gPart1Zone3Fault.state != ON) {
			
				logInfo("ECHO","Echo_BackYard_LastVoiceCommand heard was --> " + Echo_BackYard_LastVoiceCommand.state.toString())
				
				extract_date_time_formatted = now.format(java.time.format.DateTimeFormatter.ofPattern("MM_dd_yyyy_HH_mm"))
				val string PatioDoorCam = "PatioDoor"+ extract_date_time_formatted +".jpg"
				
				if (DVR.state == ON) {	
				
					executeCommandLine(Duration.ofSeconds(5), "wget", "-O", "/var/lib/openhab/pics/"+ PatioDoorCam,  "http://user:pass@192.168.0.11:81/ISAPI/Streaming/channels/501/picture" )
				}
				
				var MailBinding = getThingStatusInfo("mail:smtp:4228b22a33")
				if ((MailBinding !== null) && (MailBinding.getStatus().toString() == 'ONLINE' && gInternet.state == ON && gPort25.state == ON)) {	

					val	mailActions = getActions("mail","mail:smtp:4228b22a33")
					val String subjectemailEchoBackyard	= "openHAB3 - Echo Backyard Used"	
					val String bodyemailEchoBackyard 	= "Echo_BackYard_LastVoiceCommand heard was --> " + Echo_BackYard_LastVoiceCommand.state.toString() + "."
					val String attachment				= "/var/lib/openhab/pics/" + PatioDoorCam
					val String attachmentUrlListPushOver = attachment				
					val List<String> attachmentUrlList  = newArrayList("file://" + attachment)
					val String bodyemailEchoBackyardSMS = ''
					mailActions.sendMail(JaygMail, subjectemailEchoBackyard, bodyemailEchoBackyard, attachmentUrlList)
					logInfo("EMAIL",subjectemailEchoBackyard)			

					if (gInternet.state == ON) {

						var String PushOverMessage = "Echo Used"
						var String PushOverTitle   = "Echo Backyard"
						val pushOverActions 	   = getActions("pushover","pushover:pushover-account:account")
						pushOverActions.sendAttachmentMessage(PushOverMessage, PushOverTitle, attachmentUrlListPushOver, PushOverMIME)
						logInfo("PUSHOVER",PushOverMessage)	
					}
						
					if (gInternet.state == ON && gPort25.state == ON && UnifiPhones.state == OFF) {
					
						val	mailActions = getActions("mail","mail:smtp:4228b22a33")
						logInfo("ECHO","Echo BackYard was used by someone other than our family members.")		
						mailActions.sendMail(JaySMS, subjectemailEchoBackyard, bodyemailEchoBackyardSMS)
						logInfo("EMAIL",subjectemailEchoBackyard)
					}
				}	
			}
		}	
end

Best, Jay