Python 3 module that emulates Belkin WeMo devices for use with the Amazon Echo.
Originally forked from https://github.com/makermusings/fauxmo, unforked to enable GitHub code search (which currently doesn't work in a fork), and because the libraries have diverged substantially.
The Amazon Echo is able to control certain types of home automation devices by voice. Fauxmo provides emulated Belkin Wemo devices that the Echo can turn on and off by voice, locally, and with minimal lag time. Currently these Fauxmo devices can be configured to make requests to an HTTP server or to a Home Assistant instance via its Python API and only require a JSON config file for setup.
As of version v0.4.0, Fauxmo uses several API features and f-strings that require Python 3.6+. I highly recommend looking into pyenv if you're currently on an older Python version and willing to upgrade. Otherwise, check out the FAQ section at the bottom for tips on installing an older Fauxmo version (though note that I will not be continuing development or support for older versions).
For what it's worth, if you're concerned about installing pyenv on a low-resource machine like the Raspberry Pi, I encourage you to review my notes on the size and time required to install Python 3.6 with pyenv on a Raspberry Pi and the nontrivial improvement in speed (with a simple pystone benchmark) using an optimized pyenv-installed 3.6 as compared to the default Raspbian 3.5.3.
WeMo: Belkin home automation product with which the Amazon Echo can interface
\ˈfō-mō\): Python 3 module that emulates Belkin WeMo devices for use
with the Amazon Echo.
Fauxmo has a server component that helps register "devices" with the Echo (which may be referred to as the Fauxmo server or Fauxmo core). These devices are then exposed individually, each requiring its own port, and may be referred to as a Fauxmo device or a Fauxmo instance. The Echo interacts with each Fauxmo device as if it were a separate WeMo device.
Installation into a venv is highly recommended, especially since it's baked into the recent Python versions that Fauxmo requires.
Additionally, please ensure you're using a recent version of pip (>= 9.0.1)
prior to installation:
pip install --upgrade pip
python3 -m venv .venv
python3 -m pip install fauxmo
fauxmo -c config.json [-v]
This is a good strategy for testing features in development -- for actually contributing to development, clone the repo as per below)
python3 -m venv .venv
pip install [-e] git+https://github.com/n8henrie/fauxmo.git@dev
git clone https://github.com/n8henrie/fauxmo.git
python3 -m venv .venv
pip install -e .[dev,test]
cp config-sample.json config.json
NB: As discussed in #20, the
example files in
extras/ are not included when you install from PyPI*
pip). If you want to use them, you either need to clone the repo or
you can download them individually using tools like
navigating to the file in your web browser, clicking the
Raw button, and
using the resulting URL in your address bar.
* As of Fauxmo v0.4.0
extras/ has been added to
MANIFEST.in and may be
included somewhere depending on installation from the
format -- if you can't find them, you should probably just get the files
manually as described above.
sudo useradd -r -s /bin/false fauxmo
sudo cp extras/fauxmo.service /etc/systemd/system/fauxmo.service
sudo systemctl enable fauxmo.service
sudo systemctl start fauxmo.service
cp extras/com.n8henrie.fauxmo.plist ~/Library/LaunchAgents/com.n8henrie.fauxmo.plist
StandardErrorPathsections if desired
launchctl load ~/Library/LaunchAgents/com.n8henrie.fauxmo.plist
launchctl start com.n8henrie.fauxmo
Plugins are small user-extendible classes that allow users to easily make their own actions for Fauxmo to run by way of Alexa commands. They were previously called Handlers and may be referred to as such in places in the code and documentation.
Fauxmo v0.4.0 implements a new and breaking change in the way Handlers were
implemented in previous versions, which requires modification of the
config.json file (as described below).
A few plugins and the ABC from which the plugins are required to inherit may
be included and installed by default in the
fauxmo.plugins package. Any
pre-installed plugins, like the rest of the core Fauxmo code, have no third
So far, the pre-installed plugins include:
SimpleHTTPPlugin responds to Alexa's
off commands by making
requests to URL endpoints by way of
urllib. Example uses cases
relevant to the IOT community might be a Flask server served from localhost
that provides a nice web interface for toggling switches, whose endpoints could
be added as the
off_cmd args to a
to allow activation by way of Alexa -> Fauxmo.
As of Fauxmo v0.4.5, the
FauxmoPlugin abstract base class (and therefore all
derivate Fauxmo plugins) requires a
get_state method, which tells Alexa a
device's state. If you don't have a way to determine devices state, you can
just have your
get_state method return
"unknown", but please review the
Also, see details regarding plugin configuration in each class's docstring,
which I intend to continue as a convention for Fauxmo plugins. Users hoping to
make more complicated requests may be interested in looking at
fauxmo-plugins repository, which uses Requests
for a much friendlier API.
Users can easily create their own plugins, which is the motivation behind most of the changes in Fauxmo v0.4.0.
To get started:
Decide on a name for your plugin class. I highly recommend something
descriptive, CamelCase and a
Plugin suffix, e.g.
I strongly recommend naming your module the same as the plugin, but in all
lower case, e.g.
Note the path to your plugin, which will need to be included in your
path (absolute path recommended,
~ for homedir is
Write your class, which must at minimum:
device.on()succeeded then return
"on"), your plugin can return
get_state()method. Some of the included plugins can be configured to have this behavior using a
use_fake_stateflag in their configuration (please look at the documentation and source code of the plugins for further details). Note that this means it won't update to reflect state changes that occur outside of Fauxmo (e.g. manually flipping a switch, or toggling with a different program), whereas a proper
get_stateimplementation may be able to do so.
Any required settings will be read from your
config.json and passed into
your plugin as kwargs at initialization, see below.
In addition to the above, if you intend to share your plugin with others, I strongly recommend that you:
Be aware, when fauxmo loads a plugin, it will add the directory
containing the plugin to the Python path, so any other Python modules in this
directory might be loaded by unscrupulous code. This behavior was adopted in
part to facilitate installing any plugin dependencies in a way that will be
available for import (e.g.
cd "$MYPLUGINPATH"; pip install -t $MYPLUGINDEPS).
NB: You may need to manually install additional dependencies for these to work -- look for the dependencies in the module level docstring.
SimpleHTTPPlugin, but uses Requests for a simpler API and easier modification.
I recommend that you copy and modify
Fauxmo will use whatever config file you specify with
-c or will search for
config.json in the current directory,
that order). The minimal configuration settings are:
FAUXMO: General Fauxmo settings
ip_address: Optional[str] - Manually set the server's IP address. Recommended value:
PLUGINS: Top level key for your plugins, values should be a dictionary of (likely CamelCase) class names, spelled identically to the plugin class, with each plugin's settings as a subdictionary.
ExamplePlugin: Your plugin class name here, case sensitive.
path: The absolute path to the Python file in which the plugin class is defined (please see the section on user plugins above). Required for user plugins / plugins not pre-installed in the
example_var1: For convenience and to avoid redundancy, your plugin class can optionally use config variables at this level that will be shared for all
DEVICESlisted in the next section (e.g. an api key that would be shared for all devices of this plugin type). If provided, your plugin class must consume this variable in a custom
DEVICES: List of devices that will employ
name: Optional[str] -- Name for this device. Optional in the sense that you can leave it out of the config as long as you set it in your plugin code as the
_nameattribute, but it does need to be set somewhere. If you omit it from config you will also need to override the
__init__method, which expects a
port: Optional[int] -- Port that Echo will use connect to device. Should be different for each device, Fauxmo will attempt to set automatically if absent from config. NB: Like
name, you can choose to set manually in your plugin code by overriding the
_portattribute (and the
__init__method, which expects a
example_var2: Config variables for individual Fauxmo devices can go here if needed (e.g. the URL that should be triggered when a device is activated). Again, your plugin class will need to consume them in a custom
Each user plugin should describe its required configuration in its module-level
docstring. The only required config variables for all plugins is
which is a
List[dict] of configuration variables for each device of that
plugin type. Under
DEVICES it is a good idea to set a fixed, high, free
port for each device, but if you don't set one, Fauxmo will try to pick a
reasonable port automatically (though it will change for each run).
for a more concrete idea of the structure of the config file, using the
SimpleHTTPPlugin for demonstration purposes. Below is a description
of the kwargs that
name: What you want to call the device (how to activate by Echo)
port: Port the Fauxmo device will run on
on_cmd: str -- URL that should be requested to turn device on.
off_cmd: str -- URL that should be requested to turn device off.
state_cmd: str -- URL that should be requested to query device state
state_method: Optional[str] = GET -- GET, POST, PUT, etc.
headers: Optional[dict] -- Extra headers
state_data: Optional[dict] -- POST data
state_response_off: str -- If this string is in contained in the response from
state_cmd, then the devices is
password: Optional[str] -- Enables HTTP authentication (basic or digest only)
use_fake_state: Optional[bool] -- If
True, override the plugin's
get_statemethod to return the latest successful action as the device state. NB: The proper json boolean value for Python's
I am not a technology professional and make no promises regarding the security
of this software. Specifically, plugins such as
arbitrary code from your configuration without any validation. If your
configuration can be tampered with, you're in for a bad time.
That said, if your configuration can be tampered with (i.e. someone already has write access on your machine), then you likely have bigger problems.
Regardless, a few reasonable precautions that I recommend:
fauxmoin a virtulaenv, even without any dependencies
fauxmoas a dedicated unprivileged user with its own group
fauxmouser and group for your config file and any plugin files (perhaps
chmod 0640 config.json; chown me:fauxmo config.json)
ufw, but don't forget that you'll need to open up ports for upnp (
1900, UDP) and ports for all your devices that you've configured (in
For example, if I had 4 echo devices at 192.168.1.5, 192.168.1.10,
192.168.1.15, and 192.168.1.20, and Fauxmo was configured with devices at each
of port 12345-12350, to configure
ufw I might run something like:
for ip in 5 10 15 20; do sudo ufw allow \ from 192.168.1."$ip" \ to any \ port 1900 \ proto udp \ comment "fauxmo upnp" sudo ufw allow \ from 192.168.1."$ip" \ to any \ port 12345:12350 \ proto tcp \ comment "fauxmo devices" done
You use Fauxmo at your own risk, with or without user plugins.
Your first step in troubleshooting should probably be to "forget all devices" (which as been removed from the iOS app but is still available at alexa.amazon.com), re-discover devices, and make sure to refresh your device list (e.g. pull down on the "devices" tab in the iOS app, or just close out the app completely and re-open).
logging.INFO) is a good place to start when debugging
python -m json.tool < config.json
jsonlintor one of numerous online tools
pip install git+git://email@example.com
pip install git+git://github.com/n8henrie/fauxmo.git@d877c513ad45cbbbd77b1b83e7a2f03bf0004856
sudo install -o $(whoami) -g $(whoami) -d /opt/pyenv git clone https://github.com/pyenv/pyenv /opt/pyenv cat <<'EOF' >> ~/.bashrc export PYENV_ROOT="/opt/pyenv" export PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init -)" EOF source ~/.bashrc pyenv install 3.7.3
You can then install Fauxmo into Python 3.7 in a few ways, including:
# Install with pip "$(pyenv root)"/versions/3.7.3/bin/python3.7 -m pip install fauxmo # Show full path to Fauxmo console script pyenv which fauxmo # Run with included console script fauxmo -c /path/to/config.json -vvv # I recommend using the full path for use in start scripts (e.g. systemd, cron) "$(pyenv root)"/versions/3.7.3/bin/fauxmo -c /path/to/config.json -vvv # Alternatively, this also works (after `pip install`) "$(pyenv root)"/versions/3.7.3/bin/python3.7 -m fauxmo.cli -c config.json -vvv