Virtual WeMo Code for Amazon Echo

In the previous post, Amazon Echo and Home Automation, I talked about deciphering the UPnP protocol that the Amazon Echo uses to find and control Belkin WeMo switches. This is an update to that hack that improves the integration and makes it easier to do. The code is provided.

No More Dedicated IP Addresses

When the Amazon Echo searches for WeMo devices, the answer from each switch is formatted as an HTTP response with several headers. One of those headers is LOCATION.

 HTTP/1.1 200 OK ## copy
 CACHE-CONTROL: max-age=86400
 DATE: Mon, 22 Jun 2015 17:24:01 GMT
 EXT:
 LOCATION: http://192.168.5.190:49153/setup.xml
 OPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01
 01-NLS: 905bfa3c-1dd2-11b2-8928-fd8aebaf491c
 SERVER: Unspecified, UPnP/1.0, Unspecified
 X-User-Agent: redsonic
 ST: urn:Belkin:device:**
 USN: uuid:Socket-1_0-221517K0101769::urn:Belkin:device:**

It turns out that the Amazon Echo does respect the LOCATION header. This is very good news. It means that a single machine with one IP address can emulate many virtual switches just by having each one use a different port.

One Port Is Not Enough

It would be even nicer if many virtual switches could all share the same port, each one using a different URL. This would have made it more practical for situations where port forwarding was needed. But in a home environment where the Amazon Echo and the machine hosting the virtual switches are probably on the same network anyway, this isn’t really that big a deal.

The reason it doesn’t work is because the Amazon Echo is programmed to know the specific URL for sending on and off commands to the switches. It does not get this URL from the device definition file (setup.xml). So the Echo is going to use the same URL for all devices, and the only way to differentiate them is by their port number.

Much Simpler setup.xml

Because the Amazon Echo has hard-coded knowledge about WeMo devices, it doesn’t need to get very much configuration info from the device definition file. In fact, it ignores the large majority of it and works just fine if most of the file isn’t even there. In my tests, I was able to reduce the setup.xml contents from 133 lines down to 11 lines with everything still working. The 11 remaining lines are all required by the UPnP specification and aren’t specific to Belkin. All of the optional content authored by Belkin is unnecessary. (There are several elements required by the specification that the Echo doesn’t check for, so I left those out, too.)

The best result of this testing is that I can now publish the code because it no longer contains a copy of the setup.xml from the WeMo devices. The code is fully operational using just required UPnP elements.

<?xml version="1.0"?>
<root>
  <device>
    <deviceType>urn:MakerMusings:device:controllee:1</deviceType>
    <friendlyName>%(device_name)s</friendlyName>
    <manufacturer>Belkin International Inc.</manufacturer>
    <modelName>Emulated Socket</modelName>
    <modelNumber>3.1415</modelNumber>
    <UDN>uuid:Socket-1_0-%(device_serial)s</UDN>
  </device>
</root>
Status Code Is All You Need

When the Amazon Echo send an on or off command to the switch, the actual WeMo devices return a blob of SOAP-formatted content in the body of the HTTP response. The Echo ignores this content and reacts only to the status code. If it gets back a 200 status code, it says, “OK”. If it gets back an error code or nothing at all, then it tells you it couldn’t perform your request. So that’s the other piece of data that comes from WeMo devices that our virtual switches don’t need to copy.

Real WeMo response:

HTTP/1.1 200 OK
CONTENT-LENGTH: 295
CONTENT-TYPE: text/xml; charset="utf-8"
DATE: Mon, 22 Jun 2015 22:45:57 GMT
EXT:
SERVER: Unspecified, UPnP/1.0, Unspecified
X-User-Agent: redsonic

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body>
<u:SetBinaryStateResponse xmlns:u="urn:Belkin:service:basicevent:1">
<CountdownEndTime>0</CountdownEndTime>
</u:SetBinaryStateResponse>
</s:Body> </s:Envelope>

Virtual switch response that works just fine:

HTTP/1.1 200 OK
CONTENT-LENGTH: 0
CONTENT-TYPE: text/xml; charset="utf-8"
DATE: Mon, 22 Jun 2015 22:45:57 GMT
EXT:
SERVER: Unspecified, UPnP/1.0, Unspecified
X-User-Agent: redsonic
So Where’s the Code?

The code is right here on GitHub.

Here’s the part that you’ll want to look at and edit before you run it:

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):
        r = requests.get(self.on_cmd)
        return r.status_code == 200

    def off(self):
        r = requests.get(self.off_cmd)
        return r.status_code == 200

FAUXMOS = [
    ['office lights', rest_api_handler('http://192.168.5.4/ha-api?cmd=on&a=office', 'http://192.168.5.4/ha-api?cmd=off&a=office')],
    ['kitchen lights', rest_api_handler('http://192.168.5.4/ha-api?cmd=on&a=kitchen', 'http://192.168.5.4/ha-api?cmd=off&a=kitchen')],
]

The virtual switches expect an object that has on() and off() methods. The class I provided as an example just makes a request to a URL that you define. If you have a simple web API for your home automation, then this may work great for you. If not, then you’ll want to make your own class and run any code you want in your on() and off() methods.

If you use the example class, you will need the python-requests library. All the other libraries used are part of the standard Python installation.

FacebookTwitterGoogle+EmailEvernotePocket

76 comments

  1. This is awesome – I really appreciate being able to just run the file and get things to work.

    Do you take pull requests? We’re likely going to be doing some cleanup work (tests, comments, etc) and adding MQTT support (which is what our own home automation setup uses), and it’d be great to collaborate.

      1. No, that’s not what this does. I don’t have a WeMo Maker, so I can’t tell you for sure, but I assume that the Echo can see your WeMo Maker without having to hack anything, as long as the Maker responds to the same network commands that the WeMo switches do. If it doesn’t, I’m afraid my code won’t help you.

          1. It’s too bad that Amazon’s code doesn’t support the Maker.

            If I were trying to get it to work, I’d treat the Maker like the rest of my home automation pieces that the Echo doesn’t support, and use my virtual WeMo switches as a bridge to tie everything together. You will need a way to control your Maker from Python, and then you’d have all the necessary pieces.

  2. I’m a bit new to coding but I’d like to give this a try with my echo… First question I have is can this code be run on an Always on osx machine or is it just Ubuntu?

    And what are the steps needed to actually run your code?

    Thank you for this guide so far, you’re one few that have been able to extend the capabilities of the echo successfully

    1. You should be able to run the code on your Mac. Because it’s written in Python, it should work on almost any OS with little or no changes. Python has been installed by default in Mac OS X for a while now.

      Take a look at https://docs.python.org/2/using/mac.html for some initial help learning how to access Python on your Mac and run Python scripts. Once you’re able to do that, the instructions with the code at https://github.com/makermusings/fauxmo should help you get my code running.

      1. Running this on Mac OSX (10.9.5) with python (2.7.5) I get this:

        “`
        02j175pdv33:isy_stuff bsteinbeiser$ ./isy_echo_test.py -d
        Traceback (most recent call last):
        File “./isy_echo_test.py”, line 375, in
        p = poller()
        File “./isy_echo_test.py”, line 68, in __init__
        self.poller = select.poll()
        AttributeError: ‘module’ object has no attribute ‘poll’
        “`

        Any help appreciated!

        1. Yeah, the poll() function is broken on MacOS and therefore is not supported in Python for the Mac.

          The select library supports other polling mechanisms; it essentially exposes whatever the OS supports. Let me look into an update to the code that will use kevent on Macs.

  3. Chris,

    I’d love to see how you handle the ISY994 REST authorization, I think I have the same model as you have.

      1. When using Python to access web servers, I like to use the python-requests library. It makes the simple stuff much easier.

        Try this:

        import requests
        from requests.auth import HTTPBasicAuth
        
        ISY = 'http://192.168.0.10'
        USERNAME = 'user'
        PASSWORD = 'pass'
        
        def TurnOff(address):
          r = requests.get(ISY + '/rest/nodes/%s/cmd/DOF' % address, auth=HTTPBasicAuth(USERNAME, PASSWORD))
        

        1. Hey Chris,

          Got this running on my raspi! Now trying to add you auth code. Its not quite working (due to my poor python skills no doubt). Any hints? Thanks for your help on this!

          class isy_rest_handler(object):
              def __init__(self, address):
                  self.address = address
          
              def on(address):
                  r = requests.get(ISY + '/rest/nodes/%s/cmd/DON' % address, auth=HTTPBasicAuth(USERNAME, PASSWORD))
                  return r.status_code == 200
          
              def off(address):
                  r = requests.get(ISY + '/rest/nodes/%s/cmd/DOF' % address, auth=HTTPBasicAuth(USERNAME, PASSWORD))
                  return r.status_code == 200
          
          FAUXMOS = [
              ['mantle light', isy_rest_handler('28%2020%206D%201')],
          ]
          
          
          1. You’re so close! I assume you’ve confirmed that the URL works if you type it into your browser and give it your credentials when it asks.

            Here’s the code you need, I think. I didn’t test it, but I only tweaked yours a little.

            class isy_rest_handler(object):
                def __init__(self, address):
                    self.address = address
            
                def on(self):
                    r = requests.get(ISY + '/rest/nodes/%s/cmd/DON' % self.address, auth=HTTPBasicAuth(USERNAME, PASSWORD))
                    return r.status_code == 200
            
                def off(self):
                    r = requests.get(ISY + '/rest/nodes/%s/cmd/DOF' % self.address, auth=HTTPBasicAuth(USERNAME, PASSWORD))
                    return r.status_code == 200
            

  4. APPLE-MEDIA-CENTER:fauxmo-master JD$ sudo ./fauxmo.py
    File “./fauxmo.py”, line 367
    SyntaxError: Non-ASCII character ‘\xe2’ in file ./fauxmo.py on line 367, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
    APPLE-MEDIA-CENTER:fauxmo-master JD$

    not sure what i did wrong when i change the names on line 367?
    can you help me

  5. FAUXMOS = [
    [‘fireplace’, rest_api_handler(‘http://10.0.1.86/ha-api?cmd=on&a=fireplace’, ‘http://10.0.1.86/ha-api?cmd=off&a=fireplace’)],
    [‘kitchen lights’, rest_api_handler(‘http://192.168.5.4/ha-api?cmd=on&a=kitchen’, ‘http://192.168.5.4/ha-api?cmd=off&a=kitchen’)],
    ]

  6. Just wanted to thank you again for this Chris. over the weekend I added your script to my Mac and I can now trigger light scenes with my Hue Lights (one set scene and and a Random option). For extra credit I added pyHarmony into the mix and can now turn on and off activities with Echo. The future rocks.

    I imagine now that I’ve done this, Amazon will begin supporting Harmony and Hue Light scenes…

  7. On Windows 8.1, I get
    File “D:\_PDN\software\GitHub\Wemo-Switch-Emulator\fauxmo.py”, line 376, in p = poller()
    File “D:\_PDN\software\GitHub\Wemo-Switch-Emulator\fauxmo.py”, line 72, in __init__self.poller = select.poll()
    AttributeError: ‘module’ object has no attribute ‘poll’
    ================
    What did I forget?

    1. It’s not you; it’s Python. The Python select library only supports the methods that are provided by the underlying OS, and Windows doesn’t support poll(). This is one of those rare cases where Python does a poor job of making its libraries work across platforms.

      I’ll work on an update of the code in GitHub so that it handles Linux, Mac, and Windows and their different ways of handling I/O polling.

      1. I’ve uploaded a newer version that will hopefully work on systems where poll() isn’t supported. I’ve tested it with Python 2.7 and not 3, so there may be other issues.

      2. I switched to running the program on the Rasp Pi with Python 2 and the problem disappeared. This appears to be a Windows compatibility issue.

        1. Sorry, I didn’t see your reply before my last post. Anyway, since fauxmo will eventually be running on a Rasp Pi, I might was well do my testing there. I just thought Windows might be easier during testing since I am not a Linux guru, but I’m learning!

        2. Peter, just fyi. I had problems on win as well, even after Chris’s update. You have to disable windows network discovery. It’s already using uPnP port 1900.

          Chris, Thanks for this wonderful piece of code. It saved me a ton of time..

    1. Since I don’t have a WeMo Maker, or any experience with one, you will need to get some code working to control it first, ideally in Python. Once you have that, my virtual switches can be a bridge between the Echo and your code.

      If you don’t have Python code to control the WeMo Maker, you’ll need to focus on that first. I’m sorry that I can’t help with that.

  8. Hi Chris,

    Awesome work! Thanks for posting all of this! I tried running the code on my Ubuntu machine. It successfully gets the local address and sets up the FauxMo device and drops into ‘main loop’ (according to debug mode). But, then when I tell the Echo to discover devices, it only finds the one actual Wemo switch on the network. The FauxMo script never indicates receiving the initial UDP packet. Could the real Wemo switch be interfering? Any suggestions welcome.

    1. I don’t think the real WeMo can interfere. You should at least see the debug message that fauxmo is responding to the Echo’s search request.

      Find the do_read(self, fileno) method near line 322 of fauxmo.py and change the else: portion so the method looks like this with the two print statements:

          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:
                          time.sleep(0.5)
                          device.respond_to_search(sender, 'urn:Belkin:device:**')
                  else:
                      print "Got a UPnP broadcast message that wasn't a WeMo search:"
                      print data
      

      This will essentially make it a UPnP monitor. You’ll see all searches and device announcements that your Ubuntu machine is receiving. If you don’t see any activity from the Echo, I’d suspect a network configuration. I had to fiddle with the settings on my router to make it pass UPnP broadcasts reliably between my wireless and wired networks.

  9. Amazing tool you’ve built here. I’m a retired military IT guy who still likes to tinker.
    I have been learning to program and put ideas into functional projects as I go.

    I recently got an Amazon Echo, and saw the article on Hackaday about your WeMo emulation, and have been toying with it as a means to turn my custom surveillance system on/off by voice command. I’ve yet to work with Python though, so I can only barely parse portions of your script. For my use case, I’ll only have the one emulated switch.

    I have it working, but noticed you said that the emulated WeMo switch would likely change ports every time the script is restarted. I assume this would break the binding and require removing and re-discovering the device via the echo? I’d like to avoid this as I do have to restart my server occasionally for updates, but I’m not sure how to modify the script to have it use a static port. Could you give some advice on where changes to need to be made, or put a variables in the top of the script that could override auto port assignment with the specified value as an option? Is it as simple as putting a number value in place of self.port on line 177?

    Any help is greatly appreciated, and thanks for sharing your script!

    Lucas

    1. Lucas–

      It’s very easy as long as you’re only going to emulate one device. (Handling more than one is almost as easy, too; just two more lines of code.) Anyway, find this line near the end:

          switch = fauxmo(one_faux[0], u, p, None, 0, action_handler = one_faux[1])
      

      and change it to this:

          switch = fauxmo(one_faux[0], u, p, None, 49153, action_handler = one_faux[1])
      

      That will force it to use port 49153 every time, which is the port that the real WeMo devices use.

      By the way, if you’re only talking about infrequent restarts, you may not even have to force the Echo to forget and rediscover your virtual device. Once you have any connected devices, the Echo automatically performs a new search periodically. I haven’t checked, but it may be as often as several times a day. This should pick up any port changes without you having to do anything.

      1. I tried the code snippet you suggested, but the script errors out with “socket.error: [Errno 10013] An attempt was made to access a socket in a way forbidden by its access permissions”.

        Since you said the Echo will rescan periodically and keep itself updated on devices, I’ll keep the 0 value and let the port change dynamically and see if I run into any trouble. How does the Echo associate the old port with the new port, based on the common name string?

        1. OK, so it appears 49153 was already in use by another Windows process (WSE2012). I used netstat to find an unused port, and it appears to be working normally again.

          Just wanted to share in case anyone else stumbled across this.

  10. Well, I’m getting close! Echo discovers my faux device and fauxmo debug shows
    Responding to search for coffee pot
    Responding to search for coffee pot
    Responding to setup.xml for coffee pot
    Responding to setup.xml for coffee pot

    When I tell Echo “Turn coffee pot on”, debug prints
    Responding to ON for coffee pot
    Responding to search for coffee pot
    Responding to search for coffee pot
    Responding to setup.xml for coffee pot
    Responding to setup.xml for coffee pot
    Responding to ON for coffee pot

    BUT then after a brief pause, Echo says “The device or group Coffee Pot is not responding at the moment”.
    I just have a dummy HTTP call in the FAUXMO entry since I don’t have my handler done yet.
    Q: Want response is Echo looking for that it is not getting?
    Q: Is my handler supposed to give that response or does fauxmo do it?

    1. Peter–

      Post your FAUXMO entry here and I may be able to give more specific help.

      But, in general, the second item in each FAUXMO entry needs to be an object that has on() and off() methods. The example rest_api_handler class does this. If you’re not creating a rest_api_handler object in your FAUXMO entry, you should, especially if you’re just using a dummy HTTP URL.

      If you are already using the rest_api_handler in your FAUXMO entry, then the on() and off() methods will return True if the HTTP request succeeds (status code 200). So if you put in a URL that isn’t found and it gets a 404 error, then the Echo will report failure. For testing, you can just use any valid URL (like http://www.google.com) that you know will succeed.

      1. http://www.google.com DID eliminate the error.
        Now I need to create my handler.
        Would you be willing to share the code you put in “ha-api”? If necessary I can recode it into some language I am familiar with, like PHP. Thanks again!

        1. Peter–

          My ha-api code is a huge Python web service cobbled together over many years. I’ve got a goal to clean it up and share it on GitHub, but right now it’s got lots of hard-coded local things in it.

  11. This is fantastic. I was able to very quickly get a test setup going to turn on/off one of my Hue bulbs (I know, silly test since they’re already supported, but it was easy to do as a test!) It looks like right now this just handles the commands “on” and “off”. Do you know if its possible to do anything else? I don’t know anything about the wemos, but with the Hues you can tell the Echo to turn the lights up or down, or set them to a specific percent.

    1. Jake–

      I’m glad you got it working!

      The method used by the Echo to control the WeMos is literally “setbinarystate” and can only do on and off. The Echo does appear to respond to a few other commands, like, “Alexa, open the garage door” but it appears to treat these the same as “on” commands. Strangely, it doesn’t seem to handle “close”. (And the handling of “open” may change since that word is also supposed to launch an Alexa Skill app now.)

      1. Bummer, I was hoping it would understand the same commands as the Hue — then I’d be able to adapt them to control my Nest thermostat :-)

  12. This doesn’t seem to work with device groups. Too bad as I wanted to make an ‘everything’ group to turn all of them off.

    Also, for some reason it won’t work on an wireless connected raspberry pi for me. Works fine on ethernet.

    1. I’m not sure what group configuration you’re using, or how you control it in your setup. I have a virtual WeMo switch called “all lights” that turns on or off all the lights, and one called “t. V. Mode” that turns on the TV, turns on the amplifier, sets the input on my TV to my home theater PC, sets the volume, and turns off a couple lights. Some of this uses “scenes” in my ISY-994i Insteon controller and some uses my own Python code. The virtual WeMo switches just get a basic on or off signal from the Echo and you can mail those to anything you wish, assuming you have the programming ability.

      As for the wireless issues, I did find that I had to fiddle with the settings on my router to get it to pass the UPnP broadcast messages to both the wired and wireless network segments.

  13. Hey Chris,

    Thanks again for your work on this, it’s working great for me!

    Have you considered taking a look a the Amazon “Dash Buttons”? These are $5 wifi switches that should be easy to re-purpose. I’m thinking that someone with better Wire Shark skills than me could discern the protocol and write something that could listen for them.

    Thanks again,
    Bob

  14. Have you run into a 14 module limit? If I add 15 or more, then Echo does not discover any devices. I comment out devices to get back down to 14 and it works again. We had seen a 28 module limit with the Hue emulator, so this looks related. Question is, why is the module limit half what it is with the Hue emulator and can it be fixed to match the 28 module limitation of the Hue?

    1. It turns out that there are a few limits in the Echo. The first one is the amount of time it will spend searching for devices. The code on Github has been updated to work better with this time limit. However, there also appears to be a hard-coded limit of 16 WeMo devices that the Echo can use. If I had to guess, I’d say it’s probably a limit to the size of the internal table that the Echo’s programmers put in place. The updated code can now provide all 16 (virtual) devices to the Echo.

  15. Hey Chris,

    Thanks for writing this and publishing the code! Your info is really helpful, and I haven’t even read everything yet. I am planning to integrate this into my ISYHelper so if I do that, would you want me to give you pull requests for any changes I need, or point you to my changes?

    Thanks,
    Jim

      1. Thanks, pull request submitted. Is it possible to setup multiple upnp listeners on the same RPi to get over the device limit? Also, do any wemo devices understand dimming?

        1. So, to answer one of my questions. Yes, you can run multiple copies of fauxmo with different devices configured in both. What I haven’t tried yet is if that allows more devices.

          1. I would be very surprised if this increased the number of devices that the Echo would control. So when you get some results, please report back!

  16. Hummmmm….

    Will haver to link this with my ISYlib

    thus to to turn on a device ( 50% brightness) just call :

    myisy.node_comm(“Garage Light”, “on”, 255)

    or
    myisy[“16 3F E5 1”].on()

  17. Has anyone test these virtual WeMos with the IFTTT website & recipes yet?

    I’m looking to create a virtual WeMo, and name it “TV.” Then, create recipes on the IFTTT website based on the status-change of the device named “TV.” e.g. IF the TV is turned ON; THEN run my Harmony activity named “TV ON” — which toggles the TV power button on, set to HDMI1, cable box on, soundbar power on, soundbar volume set to 17.

    I’d then create similar virtual-devices and recipes for “Plex.”
    (e.g. the Plex-on event would also leverage IFTTT to call a Harmony activity named PLEX, which turns does the same stuff, but instead of HDMI1, switches to my smart-TVs installed Plex player.

    Ditto for “Computer” — which would switch over to HDMI3 (where the computer is plugged into the TV.)

    I could see similar uses virtual devices named: X-Box, PlayStation, Wii, KindleFire, AppleTV, etc.

    Result: When we say, “Alexa, turn on the TV” — she says “okay” — and the TV (and related components) automatically turn on.
    Or, we can then say, “Alexa, turn on Plex” — and she would switch over to the Plex Player.

    Respective “off event’ recipes would also turn things off. (Personally, I only use ONE off recipe = for the TV — since everything is connected to it, anyway.) So, regardless of what’s actively playing — when I say, “Alexa, turn off the TV” — the TV and soundbar power-off (which is enough for me.)

    Granted, all of this is just somewhat of a workaround/hack (until Amazon finally supports Harmony hubs.)

    e.g. I wouldn’t have a way to say, “Alexa, turn up/down the volume on the soundbar.”
    Instead, it would have to sound like, “Alexa, turn ON the soundbar” (Harmony translation = turn UP the volume on the soundbar.) Thus, saying “on” to Alexa means “up” to Harmony — and “off” = “down.”

    P.S. Fair warning to everyone: When I connected my new SmartThings hub v2 to Alexa, it create a bunch of “duplicate devices” (since my Echo was already paired directly to the Hue bridge, and all of my WeMo devices.) So, we could no longer voice-control things. I had to unpair the SmartThings hub from Alexa, to get things functional again.

    Peace.

    1. I tried IFTTT for a few things, but found the delay to be intolerable. My test was simple and didn’t involve any hacks. I used the official channels to send me an email when an item was added to my to-do list on the Echo. I thought it was broken at first because of how long it took the email to get sent.

      1. Is it possible to add a property for PIN so that ifttt could connect to the emulated switches? Or the android app if not ifttt? A lot could be done with this emulator if so.

  18. I have been trying to run two Wemo emulators on two computers. This should work since they have separate static IP addresses. I was getting all devices discovered ok, but the entire lot would go “offline” now and then. I started adding port numbers thinking this would solve the problem, but now some devices work fine while others go offline immediately or simply don’t respond. I can see in the console it says “responding to ON for Bedroom” (with -d) so I know it’s reaching the fauxmo. Perhaps I am adding the port numbers wrong? I know it’s different in the latest update. I believe I add a comma followed by a different port number for each switch just inside the right bracket of each fauxmo, correct? I checked 3000-3200 with Advanced Port Scanner to make sure they are clear on both machines and then used 3001-3014 on one machine and 3101-3114 on the other machine (though in theory I could reuse the same numbers since they are on different machines but I used different ones anyway). So a typical fauxmo looks like this (for ISY994i):

    [‘Master Sink’, rest_api_handler(‘http://username:password@192.168.2.120/rest/nodes/19 37 4F 1/cmd/DON’, ‘http://username:password@192.168.2.120/rest/nodes/19 37 4F 1/cmd/DOF’),3003],

    Am I doing something wrong?

    1. Fixed it. Leading zeroes in addresses need to be dropped. For example a module at address “19 06 4F” needs to be rewritten as “19 6 4F”. That’s all it took and now everything works fine. The port numbers had nothing to do with the individual failures. I had figured this out when I first set up the emulator a couple months ago and wrote it in my notes. I must be getting old.

      Thanks so much for writing this. I have tried the Hue emulators as well, but this is easier to manage with just one file. If we could get rid of the module limitations it would be perfect. I wrote to the Echo team to ask for a variable time-out instead of the default 20 seconds. We’ll see if they listen.

  19. Just discovered fauxmo via Reddit. Thanks!

    I like the idea of running this more than the Java alternative I’d been using. But getting started, I get a syntax error on launch:

    File “C:\bats\fauxmo.py”, line 63
    print msg
    ^
    SyntaxError: Missing parentheses in call to ‘print’

    If I comment out line 63, I just get an error elsewhere, so I imagine I’m doing something wrong. Can anyone give me some advice? Running Python 3.5.0 on Win8.

    1. Took a wild guess and figured it out. I don’t know much about Python, so I installed the latest (3.5.0). Installing 2.7.0 (and requests) did the trick.

      1. I’m glad you figured it out. The Python world is currently split into the 2.x and 3.x flavors since the changes were not trivial. And thanks to lazy people like me, there’s plenty of 2.x Python code still floating around. Mea culpa.

  20. Hey everybody,

    I´m translate the py script to an application in VB.

    For Now I can listen when Alexa broadcast to search wemo devices, but when I need to respond to alexa via UDP like some : (in port 50000 in my case), I undertand it need to search again about details in setup.xml, is correct? But not working….

    HTTP/1.1 200 OK
    CACHE-CONTROL: max-age=86400
    DATE: Sun, 27 Dec 2015 05:49:30 GMT
    EXT:
    LOCATION: http://10.0.0.20:15128/setup.xml
    OPT: “http://schemas.upnp.org/upnp/1/0/”; ns=01
    01-NLS: 7d67db18-15db-431c-acf3-11d00325d2af
    SERVER: Unspecified, UPnP/1.0, Unspecified
    ST: urn:Belkin:device:**
    USN: uuid:Socket-1_0-40343617361204::urn:Belkin:device:**
    X-User-Agent: redsonic

    1. Take a look at the diagram in this post. The Echo will first send out a UDP broadcast message looking for Wemo devices, and the devices (or your VB program) need to respond over UDP. You tell the Echo the URL of the setup.xml file.

      Then the Echo requests the setup.xml file over TCP using a normal HTTP request. You’ll need to handle this incoming TCP request in your code.

      So your code needs to have both a broadcast listener for UDP and a normal TCP listener for the TCP requests.

  21. I use heyu to control my X10/insteon lights. So, I’d like to run linux “heyu” commands in response to the echo / wemo commands. Has anyone written a class for this?

  22. Hey Chris,

    Great write-up! I got an Alexa a few days ago and just finished writing an Alexa skill to control my TV using the a $40 Orvibo AllOne wifi IR emitter from Amazon. Works great, but it’s really annoying having to say “Alexa, tell the TV to turn on” instead of “Alexa, turn on the TV.” It didn’t even occur to me to emulate the Wemo interface instead of using the Alexa Skills SDK. Now I’m going to implement my TV interface using this method, thanks.

    I also appreciate the details behind the protocol, as I plan on adding support to a Wemo enabled Mr. Coffee machine that isn’t picked up by the Wemo.

    Steve

    1. Hi Steve,

      Thanks for the feedback. I 100% agree with you how annoying those few extra words are every time. Every time I say, “Alexa tell the TV to turn on” or somesuch, I half expect the Echo to come back with “Tell it yourself!” At least with “turn on” and “turn off”, we can bypass the Alexa Skills approach. I’d still like to find a way to use more natural phrasing.

    2. Steve, did you have any success with the other orvibo devices?(S20)?

      My echo arrives next week and id like to use my s20’s.

      Mike

  23. I’ve brought it up on a raspi 2. I inserted code to run a Pimoroni hat and will shortly connect relays to run the garage doors. Easily adapted – code is running three faux devices. Next step is to add some sensors and code logic so that “on” and “off” mean “open” and “close”, and not simply “toggle”. I’m very happy you sorted out all the discovery and interaction code. By the way, I’m learning Python as I go.

  24. Hi,

    I’m not sure if you are working on this anymore, but I figured out a way to get multiple devices on one port number. If you have a numeric IP address, it turns out that you can prefix each of the octets with a zero to specify octal as the number format. Furthermore, you can put as many zeros as you want and the echo will ignore them, but will pass it along in the request header. This gives a convenient way to encode a device number. On my version in an Arduino ESP8266, I put up to 15 zeros per octet for a total of 65536 addresses.

    Here is the code that I used:
    String abacus_encode(IPAddress ip, uint16_t value)
    {
    // add leading zeros to the octets of the ip address, like adding beans to an abacus
    // encoding a value of 0 will return the ip address as-is,
    // 1 will add a zero to the last octet, 2 will add two zeros, etc.
    // We add up to 15 zeros (4 bits) per octet for a total of 65536 addresses (16 bits).
    // Notice that the octet becomes octal notation when we add the zeros.
    // For example:
    // 0: 192.168.1.100
    // 1: 192.168.1.0144
    // 2: 192.168.1.00144
    // 15: 192.168.1.000000000000000144
    // 16: 192.168.01.100
    String result;
    for (int i = 0; i > 12;
    value <<= 4;

    // add the octet seperator
    if (i != 0)
    result.concat('.');

    // add the next octet
    if (count != 0)
    {
    char beans[16] = "000000000000000";
    beans[count] = 0;
    result.concat(beans);
    result.concat(String(ip[i], OCT)); // must be octal due to the leading zeros
    }
    else
    result.concat(ip[i]); // decimal
    }
    return result;
    }

    uint16_t abacus_decode(String uri)
    {
    // decode an address using the encoding technique from abacus_encode()
    uint16_t result = 0;
    bool start = true;
    for (int i = 0; i < uri.length(); ++i)
    {
    if (uri[i] == '0' && start)
    result++;
    else if (uri[i] == '.')
    start = true, result <<= 4;
    else
    start = false;
    }
    return result;
    }

Leave a Reply

Your email address will not be published. Required fields are marked *