Hi Michi,
thought about and worked on a solution that is “network based”. Works for me with 5 Amazon echo devices quite well:
This approach sniffs for network traffic and identifies the active echo device. With the key word “Alexa”, echo is starting to send 1400 byte packets through the web. I do then identify the MAC address of the device and set a StringItem in openHAB for the corresponding “active” echo device. This is then be used for the TTS command.
Works in general ok. Problem still is that also inactive echos do also send those packages from time to time. It does not happen to often, therefore the chance to have the “right” active device is good.
My python script looks like this:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from scapy.all import sniff, Ether
from datetime import datetime, timedelta
import os
#THIS HELPS TO AVOID SPAM OF STATUS UPDATES AND LIMITS
#STATUS UPDATES TO 1 PER 3 SECONDS PER DEVICE. MODIFY TO YOUR CONVENIENCE.
last_detect1 = datetime.now() - timedelta(seconds=3)
last_detect2 = datetime.now() - timedelta(seconds=3)
def pack_received(packet):
#UNCOMMENT THE FOLLOWING TO TRACE PACKETS
#packet.show() # debug statement
#DEFINE YOUR MAC OF THE ALEXA DEVICE HERE AND BELOW IN FILTER
if packet[Ether].src == 'xx:xx:xx:xx:xx:xx': # This is the MAC of the first Alexa device
global last_detect1
now = datetime.now()
if last_detect1 + timedelta(seconds=3) <= now:
last_detect1 = now
#SET IP AND PORT OF YOUR OPENHAB SYSTEM
os.system('curl --max-time 2 --connect-timeout 2 --header "Content-Type: text/plain" --request POST --data "Echo_Falk_TTS" http://[IP:PORT]/rest/items/TTS_activeDevice >/dev/null 2>&1')
if packet[Ether].src == 'xx:xx:xx:xx:xx:xx': # This is the MAC of the second Alexa device
global last_detect2
now = datetime.now()
if last_detect2 + timedelta(seconds=3) <= now:
last_detect2 = now
#SET IP AND PORT OF YOUR OPENHAB SYSTEM
os.system('curl --max-time 2 --connect-timeout 2 --header "Content-Type: text/plain" --request POST --data "Echo_Bad_TTS" http://[IP:PORT]/rest/items/TTS_activeDevice >/dev/null 2>&1')
if __name__ == "__main__":
#DEFINE YOUR MAC ADRESSES HERE AS WELL SINCE CPU LOAD MIGHT GO UP.
#IT IS GOOD TO HAVE FILTER SORTED OUT MOST OF THE PACKETS.
sniff(prn=pack_received, iface="br0", filter="ip[2:2] = 1400 and (ether src xx:xx:xx:xx:xx:xx or ether src xx:xx:xx:xx:xx:xx)", store=0, count=0)
This triggers a rule which is
var StringItem activeTTS = null
rule "Aktualisiere TTS_activeDevice"
when
Item TTS_activeDevice received command
then
activeTTS = gAlexa_TTS.members.findFirst[name.equals(receivedCommand.toString)] as StringItem
end
I do all of this to get the location of family members as spoken answer from Alexa.
Command for the echo device is e.g.:
Alexa, search for Falk
Alexa, where is Falk
This is possible though the “routine” function within the Alexa app. It allows to define a phrase and link it to a smarthome item as provided by the openHAB Alexa skill.
Alexas answers to these questions are then like
Falk is at home
Falk is nearby [SOME STREET], [SOME CITY]
I have realized this by locating the iPhone with the iCloud binding, translating the coordinates into a real address through Google’s map API and send it as TTS to the active echo device.
Even though my approach still has room for improvement, I hope that helps to identify even more use cases for your great binding!