Release Candidate and Support: Amazon Echo Control Binding

Any idea how I can install the binding manually? I’m not familiar with it. I downloaded the Jar file.

Thank you for your answer. This helps a lot!
New channels, of course would be great, but I think I get my things work now.

Thank you for your great work!
Olli

Hi @michi ,
is it possible to install the latest version of the binding via PaperUi?

Yes but just with a workaround.
You need to create a routine with your text and some random event like switching ON something. Save this routine and the remove the random event so you got an empty routine.
This will prevent Alexa from answering.
But remember that some texts are supported for routines or not recognized correct.

The latest stable release but not any of the beta releases.
You need to place them inside the addons folder of your openHAB installation.

If openHAB doesn‘t use this addon you‘re able to check what binding is used with the Karaf console.
Place the beta in your addons folder and then open your Karaf console.
Enter bundle:list and check the result.
If there are two Alexa bundles use bundle --help to check how to disable/uninstall the old one and how to activate the beta.

I would prefer not to as well but my air conditioner can only be done that way - do you know if it would be possible via the API? I’m guessing if it was or was easy you would have already done it.

This works with the openHAB Alexa Skill out of the box. The binding is not needed for this.

I’m running on the Synology platform also and I’m running OH 2.3.001 version along with Michael’s Beta 10 Echo version (manually installed in the ADD-ON directory) without any issues. I have 12 Echo’s (tower and dot’s) and all tied to the rules. I’m also using Alexa routines.

Best, Jay

Hi,

Would it be possible to add something to be able to act on alarm start/stop. And know the time of theses

And be able to create alarm from this binding to the alexa app.

Please have a look at post #1377 in this thread.

It´s currently only possible to get this information as json within a rule.
But i´m not sure if it´s really json, the result looks like plain text.

@michi Could it be that the result from
http://localhost:8080/amazonechocontrol/account1/PROXY/api/notifications
is just text in json format and not a real json?
As i´m not able to parse this correctly in a rule for json.

Hi Michael.
I get “bad requests” when I send TTS commands to 5 or 6 Echos at the same time in a rule. A part of the commands doesn’t work, but the rest is okay. Is there a solution for this problem?
Thanks and greetings,
Markus

Thank you Rainer15 for this! I made a few modifications with a HUE Bulb, only runs between 4 - 7 am, offset of 45 seconds and less logging during those checks.

rule "Guest Bedroom Echo Alarm controling HUE bed side table light"
	when
		Time cron "45 0/1 4-7 * * ?"		// run every 45 secs between 4 - 7 am
	then
	
		// read Alexa notifications - alarm, reminders, timers
		
		// logInfo("ECHO", "Echo reading notifications set")		

        	var String json = sendHttpGetRequest("http://openhab.XXXXX:8080/amazonechocontrol/account1/PROXY/api/notifications")
                
        	// get number of notifications read
        	var String length = transform("JSONPATH", "$.notifications.length()", json)
		
			if (json !== null && length !== null){

	        	// logInfo("ECHO", json)
	        	// logInfo("ECHO", "-----------")
	        	// logInfo("ECHO", "Number of notifications found: " + length)
	                     
	        	var i = 0
	        	var String status
	        	var String deviceSerialNumber
	        	var String type
	        	var String alarmtime = "NULL"
	        	var String alarmdate = "NULL"
	        	var int count = Integer::parseInt(length)
	              
	        	// for all notifications, identify ...
	        	while(i <= (count - 1)) {
			
	            	status = transform("JSONPATH", "$.notifications[" + i +"].status", json)
	            	deviceSerialNumber = transform("JSONPATH", "$.notifications[" + i + "].deviceSerialNumber", json)
	            	type = transform("JSONPATH", "$.notifications[" + i + "].type", json)
				
	            	// logInfo("ECHO", "Count: " + i)
	            	// logInfo("ECHO", "Notification status: " + status)
	            	// logInfo("ECHO", "Device serial number: " + deviceSerialNumber)
	            
	            	// An ALARM that is ACTIVE and belongs to the GUEST BEDROOM echo device
				
	            	if (type == "Alarm" && status == "ON" && deviceSerialNumber == "G090LF09715401NW") {
				
	                	alarmtime = transform("JSONPATH", "$.notifications[" + i + "].originalTime", json)
	                	alarmdate = transform("JSONPATH", "$.notifications[" + i + "].originalDate", json)
					
	                	logInfo("ECHO", "Guest Bedroom Alarm found: " + alarmtime + " " + alarmdate)
					
	                	i = count 	// only the first one is considered - exit while loop
	
	            	} 
	
	            	i = i + 1
	
	        	}
	        
	        	// An active alarm has been found
	        	if (alarmtime != "NULL") {
			
	            	var DateTime setAlarmTime = new DateTime(alarmdate + "T" + alarmtime)
	            	// logInfo("ECHO", "Guest Bedroom set alarm time used for Hue control: " + setAlarmTime.toString)		// uncomment this one to determine what alarm time was used
	            
	            	if (now.isBefore(setAlarmTime) && now.plusMinutes(20).isAfter(setAlarmTime)) {
				
	               	 logInfo("ECHO", "Guest Bedroom Alarm is within 20 minutes range")
					
	                	if (now.isBefore(setAlarmTime) && now.plusMinutes(15).isAfter(setAlarmTime)) {
					
	                    		logInfo("ECHO", "Guest Bedroom Alarm is within 15 minutes range")
						
	                    		if (now.isBefore(setAlarmTime) && now.plusMinutes(10).isAfter(setAlarmTime)) {
						
										logInfo("ECHO", "Guest Bedroom Alarm is within 10 minutes range")
	
										GuestBedLamp_Dimmer.sendCommand(new PercentType(80))			// 80%
										GuestBedLamp_ColorTemp.sendCommand(new PercentType(100))		// Full White
						
	                    		} else {
	
										GuestBedLamp_Dimmer.sendCommand(new PercentType(50))			// 50%
										GuestBedLamp_ColorTemp.sendCommand(new PercentType(100))		// Full White
								}
	
	                	} else {
	
										GuestBedLamp_Dimmer.sendCommand(new PercentType(30))			// 30%
										GuestBedLamp_ColorTemp.sendCommand(new PercentType(100))		// Full White
						}
	            	}
	        	}
            }
end	

Best, Jay

Can I call this adress from homeseer ? If my openhab server is on the serve pc as Homeseer?

I had the same issue when sending too many commands to the binding or more precisely the binding to the Amazon servers.
My only solution was a group with every echo as a member or use GroupItem Methods to build something like a dynamic group.
I don´t know why but this works…

I also noticed that sending commands too fast will end in bad request errors.
For example: Triggering a rule with only one TTS command multiple times one after the other.


This shouldn´t be a problem.
I already called this address from other machines than openHAB where the binding is running.

Hey!
I’m getting this Error currently:

org.glassfish.jersey.server.internal.process.MappableException: org.openhab.binding.amazonechocontrol.internal.HttpException: GET url 'https://alexa.amazon.de/api/behaviors/entities?skillId=amzn1.ask.1p.music' failed: Bad Request

	at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:92) ~[?:?]

	at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162) ~[171:org.glassfish.jersey.core.jersey-common:2.22.2]

	at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1130) ~[171:org.glassfish.jersey.core.jersey-common:2.22.2]

	at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:711) [172:org.glassfish.jersey.core.jersey-server:2.22.2]

	at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:444) [172:org.glassfish.jersey.core.jersey-server:2.22.2]

	at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:434) [172:org.glassfish.jersey.core.jersey-server:2.22.2]

	at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:329) [172:org.glassfish.jersey.core.jersey-server:2.22.2]

	at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) [171:org.glassfish.jersey.core.jersey-common:2.22.2]

	at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) [171:org.glassfish.jersey.core.jersey-common:2.22.2]

	at org.glassfish.jersey.internal.Errors.process(Errors.java:315) [171:org.glassfish.jersey.core.jersey-common:2.22.2]

	at org.glassfish.jersey.internal.Errors.process(Errors.java:297) [171:org.glassfish.jersey.core.jersey-common:2.22.2]

	at org.glassfish.jersey.internal.Errors.process(Errors.java:267) [171:org.glassfish.jersey.core.jersey-common:2.22.2]

	at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) [171:org.glassfish.jersey.core.jersey-common:2.22.2]

	at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) [172:org.glassfish.jersey.core.jersey-server:2.22.2]

	at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) [172:org.glassfish.jersey.core.jersey-server:2.22.2]

	at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473) [169:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2]

	at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) [169:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2]

	at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) [169:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2]

	at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) [169:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2]

	at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) [169:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2]

	at com.eclipsesource.jaxrs.publisher.internal.ServletContainerBridge.service(ServletContainerBridge.java:76) [20:com.eclipsesource.jaxrs.publisher:5.3.1.201602281253]

	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865) [85:org.eclipse.jetty.servlet:9.4.11.v20180605]

	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535) [85:org.eclipse.jetty.servlet:9.4.11.v20180605]

	at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:71) [186:org.ops4j.pax.web.pax-web-jetty:7.2.3]

	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146) [84:org.eclipse.jetty.server:9.4.11.v20180605]

	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) [82:org.eclipse.jetty.security:9.4.11.v20180605]

	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) [84:org.eclipse.jetty.server:9.4.11.v20180605]

	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257) [84:org.eclipse.jetty.server:9.4.11.v20180605]

	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595) [84:org.eclipse.jetty.server:9.4.11.v20180605]

	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255) [84:org.eclipse.jetty.server:9.4.11.v20180605]

	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1317) [84:org.eclipse.jetty.server:9.4.11.v20180605]

	at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:293) [186:org.ops4j.pax.web.pax-web-jetty:7.2.3]

	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203) [84:org.eclipse.jetty.server:9.4.11.v20180605]

	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473) [85:org.eclipse.jetty.servlet:9.4.11.v20180605]

	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564) [84:org.eclipse.jetty.server:9.4.11.v20180605]

	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201) [84:org.eclipse.jetty.server:9.4.11.v20180605]

	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1219) [84:org.eclipse.jetty.server:9.4.11.v20180605]

	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144) [84:org.eclipse.jetty.server:9.4.11.v20180605]

	at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80) [186:org.ops4j.pax.web.pax-web-jetty:7.2.3]

	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) [84:org.eclipse.jetty.server:9.4.11.v20180605]

	at org.eclipse.jetty.server.Server.handle(Server.java:531) [84:org.eclipse.jetty.server:9.4.11.v20180605]

	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:352) [84:org.eclipse.jetty.server:9.4.11.v20180605]

	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260) [84:org.eclipse.jetty.server:9.4.11.v20180605]

	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:281) [75:org.eclipse.jetty.io:9.4.11.v20180605]

	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102) [75:org.eclipse.jetty.io:9.4.11.v20180605]

	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118) [75:org.eclipse.jetty.io:9.4.11.v20180605]

	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333) [87:org.eclipse.jetty.util:9.4.11.v20180605]

	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310) [87:org.eclipse.jetty.util:9.4.11.v20180605]

	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168) [87:org.eclipse.jetty.util:9.4.11.v20180605]

	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126) [87:org.eclipse.jetty.util:9.4.11.v20180605]

	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366) [87:org.eclipse.jetty.util:9.4.11.v20180605]

	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:762) [87:org.eclipse.jetty.util:9.4.11.v20180605]

	at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:680) [87:org.eclipse.jetty.util:9.4.11.v20180605]

	at java.lang.Thread.run(Thread.java:748) [?:?]

Caused by: org.openhab.binding.amazonechocontrol.internal.HttpException: GET url 'https://alexa.amazon.de/api/behaviors/entities?skillId=amzn1.ask.1p.music' failed: Bad Request

	at org.openhab.binding.amazonechocontrol.internal.Connection.makeRequest(Connection.java:549) ~[?:?]

	at org.openhab.binding.amazonechocontrol.internal.Connection.makeRequestAndReturnString(Connection.java:407) ~[?:?]

	at org.openhab.binding.amazonechocontrol.internal.Connection.getMusicProviders(Connection.java:1256) ~[?:?]

	at org.openhab.binding.amazonechocontrol.internal.statedescription.AmazonEchoDynamicStateDescriptionProvider.getStateDescription(AmazonEchoDynamicStateDescriptionProvider.java:248) ~[?:?]

	at org.eclipse.smarthome.core.thing.internal.ChannelStateDescriptionProvider.getDynamicStateDescription(ChannelStateDescriptionProvider.java:132) ~[?:?]

	at org.eclipse.smarthome.core.thing.internal.ChannelStateDescriptionProvider.getStateDescription(ChannelStateDescriptionProvider.java:118) ~[?:?]

	at org.eclipse.smarthome.core.thing.internal.ChannelStateDescriptionProvider.getStateDescriptionFragment(ChannelStateDescriptionProvider.java:80) ~[?:?]

	at org.eclipse.smarthome.core.internal.service.StateDescriptionServiceImpl.mergeStateDescriptionFragments(StateDescriptionServiceImpl.java:104) ~[?:?]

	at org.eclipse.smarthome.core.internal.service.StateDescriptionServiceImpl.getStateDescription(StateDescriptionServiceImpl.java:90) ~[?:?]

	at org.eclipse.smarthome.core.items.GenericItem.getStateDescription(GenericItem.java:399) ~[?:?]

	at org.eclipse.smarthome.io.rest.core.item.EnrichedItemDTOMapper.considerTransformation(EnrichedItemDTOMapper.java:110) ~[?:?]

	at org.eclipse.smarthome.io.rest.core.item.EnrichedItemDTOMapper.map(EnrichedItemDTOMapper.java:62) ~[?:?]

	at org.eclipse.smarthome.io.rest.core.item.EnrichedItemDTOMapper.map(EnrichedItemDTOMapper.java:56) ~[?:?]

	at org.eclipse.smarthome.io.rest.core.internal.item.ItemResource.lambda$0(ItemResource.java:238) ~[?:?]

	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[?:?]

	at java.util.HashMap$KeySpliterator.tryAdvance(HashMap.java:1574) ~[?:?]

	at java.util.stream.StreamSpliterators$WrappingSpliterator.lambda$initPartialTraversalState$0(StreamSpliterators.java:294) ~[?:?]

	at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.fillBuffer(StreamSpliterators.java:206) ~[?:?]

	at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.doAdvance(StreamSpliterators.java:169) ~[?:?]

	at java.util.stream.StreamSpliterators$WrappingSpliterator.tryAdvance(StreamSpliterators.java:300) ~[?:?]

	at java.util.Spliterators$1Adapter.hasNext(Spliterators.java:681) ~[?:?]

	at org.eclipse.smarthome.io.rest.Stream2JSONInputStream.fillBuffer(Stream2JSONInputStream.java:94) ~[?:?]

	at org.eclipse.smarthome.io.rest.Stream2JSONInputStream.read(Stream2JSONInputStream.java:70) ~[?:?]

	at java.io.InputStream.read(InputStream.java:179) ~[?:?]

	at java.io.InputStream.read(InputStream.java:101) ~[?:?]

	at org.glassfish.jersey.message.internal.ReaderWriter.writeTo(ReaderWriter.java:115) ~[?:?]

	at org.glassfish.jersey.message.internal.AbstractMessageReaderWriterProvider.writeTo(AbstractMessageReaderWriterProvider.java:79) ~[?:?]

	at org.glassfish.jersey.message.internal.InputStreamProvider.writeTo(InputStreamProvider.java:105) ~[?:?]

	at org.glassfish.jersey.message.internal.InputStreamProvider.writeTo(InputStreamProvider.java:60) ~[?:?]

	at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:265) ~[?:?]

	at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:250) ~[?:?]

	at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162) ~[?:?]

	at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:106) ~[?:?]

	at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162) ~[?:?]

	at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:86) ~[?:?]

	... 53 more

And can someone share their .sitemap for all Bluetooth Items? not quite sure how I should use them!
I can see all bluetooth Devices under:
https://alexa.amazon.de/api/bluetooth?cached=true
But I’m not able to see any of those under:
http://192.168.XXX.XX:8080/amazonechocontrol/XXXXXXXXX/ids/?serialNumber=XXXXXXXXXXXXXX
within the bluetoothMAC section
Thanks

New Beta 2.5 (2) Release

This version supports new channels for the next reminder, alarm and timer event.
It fixes a problem with wrong character encoding for french sites and I’am proudly to present:

SSML for TTS

Download from the top most posting

6 Likes

Awesome!
Thanks for your work.

How do we use the SSML with openHAB?

Have you tried the SSML documentation from the post above?

Sure.
I tried to add <break> to a TTS but Alexa just says the word break instead of doing a break.
When addind <speak> before and </speak> after the text with a <break Alexa just says the part before break and not part after break.

Doesn´t work:
echo_TTS.sendCommand('Dies ist <break> ein Test.')

Stops at the break:
echo_TTS.sendCommand('<speak>Dies ist <break> ein Test.</speak>')

Works:
echo_TTS.sendCommand('<speak>Dies ist <break/> ein Test.</speak>')

Some tags need to be closed directly with a /> at the end.
This isn´t clearly described in the Amazon docs.

Some things like <amazon:effect name=”whispered”></amazon:effect> doesn´t work at all.

This works for me:
<speak>I want to tell you a secret.<amazon:effect name="whispered">I am not a real human.</amazon:effect>.Can you believe it?</speak>