Category Archives: Echo

AlexaPi and a Warning

Amazon DOTIt’s been a busy week already – I’ve been saving up a load of “Can we write articles for your blog?” emails and this morning I decided to take a look. The sample articles were ATTROCIOUS and now I know why so many articles are bad out there – they are written to order by people who just write stuff. Well, no thanks. I’ve asked the lot of them to remove me from their databases.

In the course of the post coming in I noted a Github notice of a new version of ALEXAPI – now for those of you who don’t live in the USA or America, Amazon Alexa is a box that you can talk to and control your home, play music (theirs, not yours) and generally buy Amazon products without needing to be able to read and write. It’s a wonderful thing. ALEXAPI claims to do the same on a Raspberry Pi or similar.

I have two of the Amazon DOT devices (which are very reasonably priced at £49 as against the full on unit which IMHO is, like the Google unit and others, way OVER priced). Very happy with them. Well, I’d be happier if they had an RJ45 connection instead of just WIFI – but that’s ok.

So what do we do with these? Well, we have shopping lists, we listen to music (on Maureen’s account as she has Prime, I don’t) and we control house heating, lighting etc. All in all they’re part of the family – and the BIRDSONG skill drives our cats NUTS which is a lot of fun.

And so it was that I found this link interesting in the email this morning. With this software, a usb mic and speaker of some kind, not only can you emulate an Alexa on a Raspberry Pi but on all manner of other devices.

Now, I long ago gave up on using a Pi, £32 for the Pi, plus powered speaker, plus decent mic plus case plus power supply comes to WAY over the cost of a ready-built Echo complete with REALLY pretty lights and a microphone array.

But this morning for a moment I was distracted – one could use an Orange Pi Zero which is only a few quid!!!  And off I went and followed the instructions. So – before I start, if you want to play with this – you CAN install this on an Orange Pi Zero (Armbian is good), it DOES work and you CAN completely uninstall if. Been there, done that.

I stuck in my USB audio adaptor, powered speaker, 3.5mm stereo microphone and installed the software. I filled in the details on Amazon which gave me the necessary keys to update the config on the AlexaPi.  I rebooted the Orange Pi Zero and…

Nothing.  As usual, audio settings. I talked to some VERY helpful people on their forums who guided me through changing the settings to the USB audio device. I tested it – audio output – perfect. Audio input – perfect. I thanked them,  rebooted and…


Well, I nearly fell off my seat. “Alexa, what time is it?” – after quite some delay (this is NOTHING like a DOT which responds almost instantly) the unit came back with the time.  I tried a radio station and LO, it played the radio station. By now I was getting excited… I could put up with the delay.

Sadly, and this is no reflection on the obviously hard work done by the designers, things went downhill from there.

“change accounts” I said, wanting to switch to my wife’s account as she has Amazon music. No other people in the account setup. That could have been just a technicality so I ignored that. remember I know exactly how to use these things as I have two DOTS.

“Set a timer” – turns out the unit does not do lists – most likely API-related.

“Find my devices” – this was the killer. It took some hunting down but it was actually in the UNINSTALL instructions that I found … “AVS API doesn't have a way to connect the devices to Amazon.”

That last one was the killer. That and the mic – the problem is – Amazon put a lot of work into the mics – and they handle speech over background music reasonably well. I can blast my music and shout over the couch “ALEXA – SHUT UP” – and it promptly obeys. Not so the AlexaPi – while playing the radio could I HELL get it to take any notice of me until I turned the music down – and I was only sitting 2ft away.

I uninstalled the lot – and my Orange Pi Zero seems to be as good as new. So if you want something new to play with – or if you have a very limited set of needs – have a play. For me – I’d rather fork out £49 at this point.

It was suggested that one thing this software could to that the real thing can’t – is respond asynchronously – i.e. use it to output speech without a command – that is an annoying omission on the Amazon system – though if you write a special skill you can have it say what you want in reply – but then you have to call the skill and have a secure connection etc. 

But then it occurred to me – I have a Raspberry Pi running the house and HABRIDGE – and it has Node-Red and I already have IVONA speech on it – all I need is a speaker and when the DOT talks to HABRIDGE to fire an MQTT control message to my lighting and heating – it can also send off some speech itself. Don’t know why I didn’t think of that before.

So there it is.


Fauxmo Alexa Delights

Amazon EchoI’m going to cut a very long story short here.  I’ve been looking at ESP8266 emulations of WEMOs because up to now this seems to be a popular device to emulate when using with your talking Amazon Echo. If anyone wants to come up with something that will take ANY word, not just ON or OFF – please do feel free to do the hard work. In another article, I described how, with the aid of a small SKILL at the Amazon end, an SSL certificate and some Node-Red code, we managed to make a generalised system to extract words out of Echo – and that is controlling my heating and all sorts right now -  marvellous. If you’re not up to speed with ECHO, MQTT or NODE-RED see earlier blogs in here.

Simple On Off

But what if you just want ON and OFF with no HTTPS, no messing at the Amazon end?  I checked out ESP8266 emulations. AWFUL. I’ll not mention names and I’m sure this was just done as a demo – but the one I tested was written in Arduino/ESP code – connected to WIFI and acted as an ON/OFF Wemo – MARVELOUS. Except that with the first sign of WIFI trouble – it fell over and died – absolutely no attempt at making it work regardless. Well as you know, WIFI dies from time to time. Bin.

So what next?

I found something others will have spotted called FAUXMO which is basically a single Python script –that emulates one or more WEMO type devices. At first it did not work – so half a day later having learned enough Python to get me by I realised that this was intended to call web pages – to turn things on and off. I understood there was an MQTT version of it – but that a friend of mine was having trouble getting that working – so  - I decided to go for broke and modify the original.

All you need here is the Pi or similar equipped with MQTT and with Python installed – Node-Red is not needed. Indeed once you see how this works – it would be very easy to take the cheapest of these little SBCs – the FriendlyArm NEO for example and make it look like several devices – instead of MQTT you could turn ports on and off in Python.

Cheapest multi-output Alexa-enabled device on the planet?

Orange Pi ZeroBefore I go further – you might have a simple requirement – far simpler than we usually cover in here – a single box that “does it all”, talking to Amazon Alexa with multiple outputs looking like multiple devices… well, the Orange Pi ZERO available at under £9 (inc shipping) from AliExpress could just be the ticket? Install Armbian, MQTT and Python – and… read on.


You need a client called Paho MQTT to bring MQTT to Python… so here’s what I did in order… we’re looking at a Pi or similar, running Node-Red and MQTT broker. In my case with username and password.

sudo pip install paho-mqtt

Seconds later, done – MQTT now available inside Python – that was easy.

I had to add a header into the code – to import mqtt – and I had to define username, password, mqtt address.

That all went into the top of the file and should be pretty obvious.

I then modified some code – and the definitions of two sample devices – “kitchen lights” and “bedroom lights”.

Here are the modifications.


import paho.mqtt.client as paho


Change to how recognised terms are actually used

class rest_api_handler(object):
    def __init__(self, on_cmd, off_cmd):
        self.on_cmd = on_cmd
        self.off_cmd = off_cmd

    def on(self):
        return 200

    def off(self):
        return 200

And finally the bit you're interested in - device definitions... you only have to change the user settings at the top then this lot.

    ['bedroom lights', rest_api_handler('toesp/bedlights|{out0:1}', 'toesp/bedlights|{out0:0}')],
    ['kitchen lights', rest_api_handler('toesp/kitchenlights|{out0:2}', 'toesp/kitchenlights|{out0:3}')],

So what you’re looking at are the words that Alexa will accept (“kitchen lights” for example) followed by ON OR OFF. The two following strings are MQTT topic and PAYLOAD separated by | for firstly ON and secondly OFF.

As you can see it is easy to add new devices – you do with the MQTT what you will – in my case this would be talking directly to devices – more likely I’ll fire instructions off that Node-Red can handle for manual override of lighting etc.

To get this all to work you need to be running the program and say “Alexa find devices” to your ECHO – it will find the devices and you’re ready to go. If you make changes – restart the program – re-find devices.

And here  is the complete – modified Python code – complete with the original author info – after all I didn’t make THAT many changes even if it did end up taking me all day.

Don’t worry about it looking over-powering – you only need to know about the stuff above – the rest is just a case of pasting into into a file.

#!/usr/bin/env python

The MIT License (MIT)
Copyright (c) 2015 Maker Musings
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

# For a complete discussion, see

import email.utils
import requests
import select
import socket
import struct
import sys
import time
import urllib
import uuid
import paho.mqtt.client as paho


# This XML is the minimum needed to define one of our virtual switches
# to the Amazon Echo

SETUP_XML = """<?xml version="1.0"?>
    <manufacturer>Belkin International Inc.</manufacturer>
    <modelName>Emulated Socket</modelName>

DEBUG = False

def dbg(msg):
    global DEBUG
    if DEBUG:
        print msg

# A simple utility class to wait for incoming data to be
# ready on a socket.

class poller:
    def __init__(self):
        if 'poll' in dir(select):
            self.use_poll = True
            self.poller = select.poll()
            self.use_poll = False
        self.targets = {}

    def add(self, target, fileno = None):
        if not fileno:
            fileno = target.fileno()
        if self.use_poll:
            self.poller.register(fileno, select.POLLIN)
        self.targets[fileno] = target

    def remove(self, target, fileno = None):
        if not fileno:
            fileno = target.fileno()
        if self.use_poll:

    def poll(self, timeout = 0):
        if self.use_poll:
            ready = self.poller.poll(timeout)
            ready = []
            if len(self.targets) > 0:
                (rlist, wlist, xlist) =, [], [], timeout)
                ready = [(x, None) for x in rlist]
        for one_ready in ready:
            target = self.targets.get(one_ready[0], None)
            if target:

# Base class for a generic UPnP device. This is far from complete
# but it supports either specified or automatic IP address and port
# selection.

class upnp_device(object):
    this_host_ip = None

    def local_ip_address():
        if not upnp_device.this_host_ip:
            temp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                temp_socket.connect(('', 53))
                upnp_device.this_host_ip = temp_socket.getsockname()[0]
                upnp_device.this_host_ip = ''
            dbg("got local address of %s" % upnp_device.this_host_ip)
        return upnp_device.this_host_ip

    def __init__(self, listener, poller, port, root_url, server_version, persistent_uuid, other_headers = None, ip_address = None):
        self.listener = listener
        self.poller = poller
        self.port = port
        self.root_url = root_url
        self.server_version = server_version
        self.persistent_uuid = persistent_uuid
        self.uuid = uuid.uuid4()
        self.other_headers = other_headers

        if ip_address:
            self.ip_address = ip_address
            self.ip_address = upnp_device.local_ip_address()

        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.bind((self.ip_address, self.port))
        if self.port == 0:
            self.port = self.socket.getsockname()[1]
        self.client_sockets = {}

    def fileno(self):
        return self.socket.fileno()

    def do_read(self, fileno):
        if fileno == self.socket.fileno():
            (client_socket, client_address) = self.socket.accept()
            self.poller.add(self, client_socket.fileno())
            self.client_sockets[client_socket.fileno()] = client_socket
            data, sender = self.client_sockets[fileno].recvfrom(4096)
            if not data:
                self.poller.remove(self, fileno)
                self.handle_request(data, sender, self.client_sockets[fileno])

    def handle_request(self, data, sender, socket):

    def get_name(self):
        return "unknown"
    def respond_to_search(self, destination, search_target):
        dbg("Responding to search for %s" % self.get_name())
        date_str = email.utils.formatdate(timeval=None, localtime=False, usegmt=True)
        location_url = self.root_url % {'ip_address' : self.ip_address, 'port' : self.port}
        message = ("HTTP/1.1 200 OK\r\n"
                  "CACHE-CONTROL: max-age=86400\r\n"
                  "DATE: %s\r\n"
                  "LOCATION: %s\r\n"
                  "OPT: \"\"; ns=01\r\n"
                  "01-NLS: %s\r\n"
                  "SERVER: %s\r\n"
                  "ST: %s\r\n"
                  "USN: uuid:%s::%s\r\n" % (date_str, location_url, self.uuid, self.server_version, search_target, self.persistent_uuid, search_target))
        if self.other_headers:
            for header in self.other_headers:
                message += "%s\r\n" % header
        message += "\r\n"
        temp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        temp_socket.sendto(message, destination)

# This subclass does the bulk of the work to mimic a WeMo switch on the network.

class fauxmo(upnp_device):
    def make_uuid(name):
        return ''.join(["%x" % sum([ord(c) for c in name])] + ["%x" % ord(c) for c in "%sfauxmo!" % name])[:14]

    def __init__(self, name, listener, poller, ip_address, port, action_handler = None):
        self.serial = self.make_uuid(name) = name
        self.ip_address = ip_address
        persistent_uuid = "Socket-1_0-" + self.serial
        other_headers = ['X-User-Agent: redsonic']
        upnp_device.__init__(self, listener, poller, port, "http://%(ip_address)s:%(port)s/setup.xml", "Unspecified, UPnP/1.0, Unspecified", persistent_uuid, other_headers=other_headers, ip_address=ip_address)
        if action_handler:
            self.action_handler = action_handler
            self.action_handler = self
        dbg("FauxMo device '%s' ready on %s:%s" % (, self.ip_address, self.port))

    def get_name(self):

    def handle_request(self, data, sender, socket):
        if data.find('GET /setup.xml HTTP/1.1') == 0:
            dbg("Responding to setup.xml for %s" %
            xml = SETUP_XML % {'device_name' :, 'device_serial' : self.serial}
            date_str = email.utils.formatdate(timeval=None, localtime=False, usegmt=True)
            message = ("HTTP/1.1 200 OK\r\n"
                       "CONTENT-LENGTH: %d\r\n"
                       "CONTENT-TYPE: text/xml\r\n"
                       "DATE: %s\r\n"
                       "LAST-MODIFIED: Sat, 01 Jan 2000 00:01:15 GMT\r\n"
                       "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n"
                       "X-User-Agent: redsonic\r\n"
                       "CONNECTION: close\r\n"
                       "%s" % (len(xml), date_str, xml))
        elif data.find('SOAPACTION: "urn:Belkin:service:basicevent:1#SetBinaryState"') != -1:
            success = False
            if data.find('<BinaryState>1</BinaryState>') != -1:
                # on
                dbg("Responding to ON for %s" %
                success = self.action_handler.on()
            elif data.find('<BinaryState>0</BinaryState>') != -1:
                # off
                dbg("Responding to OFF for %s" %
                success =
                dbg("Unknown Binary State request:")
            if success:
                # The echo is happy with the 200 status code and doesn't
                # appear to care about the SOAP response body
                soap = ""
                date_str = email.utils.formatdate(timeval=None, localtime=False, usegmt=True)
                message = ("HTTP/1.1 200 OK\r\n"
                           "CONTENT-LENGTH: %d\r\n"
                           "CONTENT-TYPE: text/xml charset=\"utf-8\"\r\n"
                           "DATE: %s\r\n"
                           "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n"
                           "X-User-Agent: redsonic\r\n"
                           "CONNECTION: close\r\n"
                           "%s" % (len(soap), date_str, soap))

    def on(self):
        return False

    def off(self):
        return True

# Since we have a single process managing several virtual UPnP devices,
# we only need a single listener for UPnP broadcasts. When a matching
# search is received, it causes each device instance to respond.
# Note that this is currently hard-coded to recognize only the search
# from the Amazon Echo for WeMo devices. In particular, it does not
# support the more common root device general search. The Echo
# doesn't search for root devices.

class upnp_broadcast_responder(object):
    TIMEOUT = 0

    def __init__(self):
        self.devices = []

    def init_socket(self):
        ok = True
        self.ip = ''
        self.port = 1900
            #This is needed to join a multicast group
            self.mreq = struct.pack("4sl",socket.inet_aton(self.ip),socket.INADDR_ANY)

            #Set up server socket
            self.ssock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,socket.IPPROTO_UDP)

            except Exception, e:
                dbg("WARNING: Failed to bind %s:%d: %s" , (self.ip,self.port,e))
                ok = False

            except Exception, e:
                dbg('WARNING: Failed to join multicast group:',e)
                ok = False

        except Exception, e:
            dbg("Failed to initialize UPnP sockets:",e)
            return False
        if ok:
            dbg("Listening for UPnP broadcasts")

    def fileno(self):
        return self.ssock.fileno()

    def do_read(self, fileno):
        data, sender = self.recvfrom(1024)
        if data:
            if data.find('M-SEARCH') == 0 and data.find('urn:Belkin:device:**') != -1:
                for device in self.devices:
                    device.respond_to_search(sender, 'urn:Belkin:device:**')

    #Receive network data
    def recvfrom(self,size):
        if self.TIMEOUT:
            ready =[self.ssock], [], [], self.TIMEOUT)[0]
            ready = True

            if ready:
                return self.ssock.recvfrom(size)
                return False, False
        except Exception, e:
            return False, False

    def add_device(self, device):
        dbg("UPnP broadcast listener: new device registered")

# This is an example handler class. The fauxmo class expects handlers to be
# instances of objects that have on() and off() methods that return True
# on success and False otherwise.
# This example class takes two full URLs that should be requested when an on
# and off command are invoked respectively. It ignores any return data.
# Clearly somewhat modified by PS to take in a string - split in two and send out to MQTT
class rest_api_handler(object):
    def __init__(self, on_cmd, off_cmd):
        self.on_cmd = on_cmd
        self.off_cmd = off_cmd

    def on(self):
        return 200

    def off(self):
        return 200

# Each entry is a list with the following elements:
# name of the virtual switch
# object with 'on' and 'off' methods
# port # (optional; may be omitted)

# NOTE: As of 2015-08-17, the Echo appears to have a hard-coded limit of
# 16 switches it can control. Only the first 16 elements of the FAUXMOS
# list will be used.

# Clearly the above is changed. Here we have MQTT commands in the form topic|payload

    ['bedroom lights', rest_api_handler('toesp/bedlights|{out0:1}', 'toesp/bedlights|{out0:0}')],
    ['kitchen lights', rest_api_handler('toesp/kitchenlights|{out0:2}', 'toesp/kitchenlights|{out0:3}')],

if len(sys.argv) > 1 and sys.argv[1] == '-d':
    DEBUG = True

# Set up our singleton for polling the sockets for data ready
p = poller()

# Set up our singleton listener for UPnP broadcasts
u = upnp_broadcast_responder()

# Add the UPnP broadcast listener to the poller so we can respond
# when a broadcast is received.

# Create our FauxMo virtual switch devices
for one_faux in FAUXMOS:
    if len(one_faux) == 2:
        # a fixed port wasn't specified, use a dynamic one
    switch = fauxmo(one_faux[0], u, p, None, one_faux[2], action_handler = one_faux[1])

dbg("Entering main loop\n")

client = paho.Client()
client.username_pw_set(mqtt_user, mqtt_pass)

while True:
        # Allow time for a ctrl-c to stop the process
    except Exception, e:


(if this lot complains about spacings - get the original article and make my changes

So – put the file in a directory – I put it into /home/pi/fauxmo/ and gave the file execute permissions (no idea if that’s needed or not but as I do that with scripts I thought it best - 0754 if you're interested).

I ran the file in the /home/pi/fauxmo folder at a terminal as:

python –d

The –d is for debug – you can scratch that once you are running – and then find a way to make it run reliably on power up. That is possibly described here:  if someone has the working command line for this please do send it in – might save some experimenting.

And that’s it. Great fun and instantly useful without lots of hassle. With Node-Red you could fire the MQTT in to do with what you want – or fire straight to MQTT-accepting ESP8266s (what use are ESPs that DON’T support MQTT you might ask) – or if you look at the chunk of code handling MQTT – you could pull that apart and instead just control ports!!

So here’s a thought – one of our readers was kind enough to remind me that the Orange Pi Zero is now available and it is CHEAP. Normally I’d not touch Orange with a bargepole but the Armbian Jessie implementation seems to be now up to speed. SO -

Under £9 for the cheapest, might not be that happy running Node-Red but it will certainly run PYTHON and MQTT (well, you don’t even need MQTT for that matter if you just want to control the odd output or send stuff through serial etc)… so for under £9 you could have several Alexa-enabled devices !!! That can’t be bad.

This will no doubt mutate as time goes on!