Package: fauxmo
Fauxmo READMEmaster:dev:Python 3 module that emulates Belkin WeMo devices for use with the Amazon Echo.Originally forked fromhttps://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.Documentation:fauxmo.readthedocs.orgIntroductionThe 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 such asHome
Assistantor to run other commands locally on the
device 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 intopyenvif 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 toreview my
noteson 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.Terminologyfaux (\ˈfō\): imitationWeMo: Belkin home automation product with which the Amazon Echo can interfaceFauxmo (\ˈ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.UsageInstallation into a venv ishighly 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 pipSimple install: From PyPIpython3 -m venv .venvsource ./.venv/bin/activatepython3 -m pip install fauxmoMake aconfig.jsonbased onconfig-sample.jsonfauxmo -c config.json [-v]As ofv0.6.0, you canoptionallyinstalluvloopfor potentially better
performance, whichmightbe helpful if you have a large number of devices or
a network with lots of broadcast mdns traffic. If it is present,fauxmowill
take advantage. It is not terribly difficult to installuvloopbut you are on
your own:https://github.com/MagicStack/uvloop.Simple install of dev branch from GitHubThis is a good strategy for testing features in development -- for actually
contributing to development, clone the repo as per below)python3 -m venv .venvsource ./.venv/bin/activatepip install [-e] git+https://github.com/n8henrie/fauxmo.git@devInstall for development from GitHubgit clone https://github.com/n8henrie/fauxmo.gitcd fauxmopython3 -m venv .venvsource ./.venv/bin/activatepip install -e .[dev,test]cp config-sample.json config.jsonEditconfig.jsonfauxmo [-v]Set up the EchoOpen the Amazon Alexa webapp to theSmart
HomepageWith Fauxmo running, click "Discover devices" (or tell Alexa to "find
connected devices")Ensure that your Fauxmo devices were discovered and appear with their
names in the web interfaceTest: "Alexa, turn on [the kitchen light]"Set Fauxmo to run automatically in the backgroundNB: As discussed in#20, the
example files inextras/arenotincluded when you install from PyPI*
(usingpip). If you want to use them, you either need to clone the repo or
you can download them individually using tools likewgetorcurlby
navigating to the file in your web browser, clicking theRawbutton, and
using the resulting URL in your address bar.* As of Fauxmo v0.4.0extras/has been added toMANIFEST.inand may be
included somewhere depending on installation from the.tar.gzvswhlformat -- if you can't find them, you should probably just get the files
manually as described above.systemd (e.g. Raspbian Jessie)Recommended: add an unprivileged user to run Fauxmo:sudo useradd -r -s /bin/false fauxmoNB: Fauxmo may require root privileges if you're using ports below 1024sudo cp extras/fauxmo.service /etc/systemd/system/fauxmo.serviceEdit the paths in/etc/systemd/system/fauxmo.servicesudo systemctl enable fauxmo.servicesudo systemctl start fauxmo.servicelaunchd (OS X)cp extras/com.n8henrie.fauxmo.plist ~/Library/LaunchAgents/com.n8henrie.fauxmo.plistEdit the paths in~/Library/LaunchAgents/com.n8henrie.fauxmo.plistYou can remove theStandardOutPathandStandardErrorPathsections if
desiredlaunchctl load ~/Library/LaunchAgents/com.n8henrie.fauxmo.plistlaunchctl start com.n8henrie.fauxmoPluginsPlugins 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 theconfig.jsonfile (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 thefauxmo.pluginspackage. Any
pre-installed plugins, like the rest of the core Fauxmo code, have no third
party dependencies.So far, the pre-installed plugins include:fauxmo.plugins.simplehttpplugin.SimpleHTTPPluginfauxmo.plugins.commandlineplugin.CommandLinePluginfauxmo.plugins.homeassistantplugin.HomeAssistantPluginSimpleHTTPPluginresponds to Alexa'sonandoffcommands by making
requests to URL endpoints by way ofurllib. 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 theon_cmdandoff_cmdargs to aSimpleHTTPPlugininstance
to allow activation by way of Alexa -> Fauxmo.As of Fauxmo v0.4.5, theFauxmoPluginabstract base class (and therefore all
derivate Fauxmo plugins) requires aget_statemethod, which tells Alexa a
device's state. If you don't have a way to determine devices state, you can
just have yourget_statemethod return"unknown", but please review the
notes onget_statebelow.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 atRESTAPIPluginin thefauxmo-plugins repository, which uses Requests
for a much friendlier API.User pluginsUsers 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 aPluginsuffix, e.g.FooSwitcherPlugin.I strongly recommend naming your module the same as the plugin, but in all
lower case, e.g.fooswitcherplugin.py.Note the path to your plugin, which will need to be included in yourconfig.jsonaspath(absolute path recommended,~for homedir is
okay).Write your class, which must at minimum:inherit fromfauxmo.plugins.FauxmoPlugin.provide the methodson(),off(), andget_state().Please note that unless the Echo has a way to determine the device
state, it will likely respond that your "device is not responding"
after you turn a device on (or in some cases off, or both), but it
should still be able to switch the device.If you want to ignore the actual device's state and just return the
last successful action as the current state (e.g. ifdevice.on()succeeded then return"on"), your plugin can returnsuper().get_state()as itsget_state()method. Some of the
included plugins can be configured to have this behavior using ause_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 properget_stateimplementation may be able to do so.If using fake state or if your device cannot readily report its state
upon request (for example if you poll for state with a background
process like mqtt), you should also set aninitial_statein your
config. As of August 2023, prior to adding a newly discovered device,
Alexa requests its state and will fail to add the device if it can't
report a state.Any required settings will be read from yourconfig.jsonand 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:Include generous documentation as a module level docstring.Note specific versions of any dependencies in that docstring.Because these user plugins are kind of "side-loaded," you will need to
manually install their dependencies into the appropriate environment, so
it's important to let other users know exactly what versions you use.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).Notable plugin examplesNB: You may need tomanuallyinstall additional dependencies for these to
work -- look for the dependencies in the module level docstring.https://github.com/n8henrie/fauxmo-pluginsRESTAPIPluginTrigger HTTP requests with your Echo.Similar toSimpleHTTPPlugin, but usesRequestsfor a simpler
API and easier modification.MQTTPluginTrigger MQTT events with your EchoUser contributions of interesting plugins are more than welcome!ConfigurationI recommend that you copy and modifyconfig-sample.json.
Fauxmo will use whatever config file you specify with-cor will search forconfig.jsonin the current directory,~/.config/fauxmo,~/.fauxmo/, and/etc/fauxmo/(in that order). The minimal configuration settings are:FAUXMO: General Fauxmo settingsip_address: Optional[str] - Manually set the server's IP address.
Recommended value:"auto".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 thefauxmo.pluginssubpackage.example_var1: For convenience and to avoid redundancy, your plugin
class canoptionallyuse config variables at this level that
will be shared for allDEVICESlisted 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__init__.DEVICES: List of devices that will employExamplePluginname: 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 anamekwarg.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: Likename, you
can choose to set manually in your plugin code by overriding the_portattribute (and the__init__method, which expects aportkwarg otherwise).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__init__.Each user plugin should describe its required configuration in its module-level
docstring. The only required config variables for all plugins isDEVICES,
which is aList[dict]of configuration variables for each device of that
plugin type. UnderDEVICESit is a good idea to set a fixed, high, freeportfor 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).Please seeconfig-sample.jsonfor a more concrete idea
of the structure of the config file, using the built-inSimpleHTTPPluginfor
demonstration purposes. Below is a description of the kwargs thatSimpleHTTPPluginaccepts.name: What you want to call the device (how to activate by
Echo)port: Port the Fauxmo device will run onon_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 statemethod/state_method: Optional[str] = GET -- GET, POST, PUT, etc.headers: Optional[dict]  -- Extra headerson_data/off_data/state_data: Optional[dict] -- POST datastate_response_on/state_response_off: str -- If this string is in
contained in the response fromstate_cmd, then the devices isonoroff, respectivelyuser/password: Optional[str] -- Enables HTTP authentication (basic or
digest only)use_fake_state: Optional[bool] -- IfTrue, override the plugin'sget_statemethod to return the latest successful action as the device
state. NB: The proper json boolean value for Python'sTrueistrue, notTrueor"true".SecurityI am not a technology professional and make no promises regarding the security
of this software. Specifically, plugins such asCommandLinePluginexecute
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:runfauxmoin a virtulaenv, even without any dependenciesrunfauxmoas a dedicated unprivileged user with its own groupremove write access from thefauxmouser and group for your config file and
any plugin files (perhapschmod 0640 config.json; chown me:fauxmo config.json)consider using a firewall likeufw, 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 (inconfig.json).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 configureufwI might run something like:$foripin5101520;dosudo 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"doneYou use Fauxmo at your own risk, with or without user plugins.Troubleshooting / FAQYour first step in troubleshooting should probably be to "forget all devices"
(which as been removed from the iOS app but is still available atalexa.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).How can I increase my logging verbosity?-v[vv]-vv(logging.INFO) is a good place to start when debuggingHow can I ensure my config is valid JSON?python -m json.tool < config.jsonUsejsonlintor one of numerous online toolsHow can I install an older / specific version of Fauxmo?Install from a tag:pip install git+git://github.com/n8henrie/fauxmo.git@v0.1.11Install from a specific commit:pip install git+git://github.com/n8henrie/fauxmo.git@d877c513ad45cbbbd77b1b83e7a2f03bf0004856Where can I get more information on how the Echo interacts with devices like
Fauxmo?Check outprotocol_notes.mdDoes Fauxmo work with non-Echo emulators like Alexa AVS or Echoism.io?Apparently not.How do I find my Echo firmware version?https://alexa.amazon.com-> Settings -> [Device Name] -> Device Software VersionInstalling Python 3.10 withpyenvsudoinstall-o$(whoami)-g$(whoami)-d/opt/pyenv
gitclonehttps://github.com/pyenv/pyenv/opt/pyenv
cat<<'EOF' >> ~/.bashrcexport PYENV_ROOT="/opt/pyenv"export PATH="$PYENV_ROOT/bin:$PATH"eval "$(pyenv init -)"EOFsource~/.bashrc
pyenvinstall3.10.6You can then install Fauxmo into Python 3.10 in a few ways, including:# Install with pip"$(pyenvroot)"/versions/3.10.6/bin/python3.10-mpipinstallfauxmo# Show full path to Fauxmo console scriptpyenvwhichfauxmo# Run with included console scriptfauxmo-c/path/to/config.json-vvv# I recommend using the full path for use in start scripts (e.g. systemd, cron)"$(pyenvroot)"/versions/3.10.6/bin/fauxmo-c/path/to/config.json-vvv# Alternatively, this also works (after `pip install`)"$(pyenvroot)"/versions/3.10.6/bin/python3.10-mfauxmo.cli-cconfig.json-vvvDocker (alpha)I'm not a heavy docker user, but I thought it might be helpful to also provide
a docker image.The Dockerfile can be run locally from a copy of the repo; you'll obviously
need to changeconfig-sample.jsonto an absolute path to yourconfig.json.$dockerrun--network=host--rm-it\-v$(pwd)/config-sample.json:/etc/fauxmo/config.json:ro\"$(dockerbuild-q.)"As far as I'm aware thenetwork=hostwill be unavoidable due to the need to
listen (and respond) to UPnP broadcasts.Buy Me a Coffee☕️Acknowledgements / Reading ListTremendous thanks to @makermusings forthe original version of
Fauxmo!Also thanks to @DoWhileGeek for commits towards Python 3 compatibilityhttp://www.makermusings.com/2015/07/13/amazon-echo-and-home-automationhttp://www.makermusings.com/2015/07/18/virtual-wemo-code-for-amazon-echohttp://hackaday.com/2015/07/16/how-to-make-amazon-echo-control-fake-wemo-deviceshttps://developer.amazon.com/appsandservices/solutions/alexa/alexa-skills-kithttps://en.wikipedia.org/wiki/Universal_Plug_and_Playhttp://www.makermusings.com/2015/07/19/home-automation-with-amazon-echo-apps-part-1http://www.makermusings.com/2015/08/22/home-automation-with-amazon-echo-apps-part-2https://www.rilhia.com/tutorials/using-upnp-enabled-devices-talend-belkin-wemo-switchChangelogWill not contain minor changes -- feel free to look throughgit logfor
more detail.v0.8.0 :: 20240219Force keyword arguments inCommandLinePluginas done elsewhereThis is really the only cause of the "highest nonzero version number" bumpFix plugins not passinginitial_stateto parent class (https://github.com/n8henrie/fauxmo/issues/122)Tweaks to nix development environmentAdd coverage testing totests/to ensure all testing code paths are takenv0.7.0 :: 20230825Addinitial_statekwarg for pluginsSee notes for eb749275a06c443bf4c914c450f9717ee3c7f212Python 3.11, drop official 3.7 supportAdd a basic config validation functionSupport config in~/.config/fauxmoFramework for nix and docker supportAdd timeouts to default plugins2f9212b67dec62a4cc9c1609fbbe59dcea1c3d27Commands that block freezeeverythingdue to the way asyncio works.
Highly recommended to leverage these timeouts for anything that may blockAdd supportshell=TruecommandsUse at your own risk :)Migrate setup.cfg to standalone pyproject.toml09f80b364b85b327ab3f92c5e6f538b001a6becctype hinting updatesv0.6.0 :: 20220304Python 3.10Add optionaluvloopsupport (https://github.com/n8henrie/fauxmo/issues/112)Add option to overridedomaintohomeassistantplugin.py(https://github.com/n8henrie/fauxmo/issues/114)v0.5.1, v0.5.2 :: 20210901Version bumps to upload new pyproject.toml format to PyPIv0.5.0 :: 20191212Add py38 supportAdduse_fake_stateoption to accommodate situations that state can't be
properly determined (thanks @johngo7470)Bugfix: fix unexpected behavior with a switch's state logic was true for bothonandoffMigrated HomeAssistantPlugin and CommandLinePlugin from fauxmo-plugins repoUpdate tests, pytest fixtures, and add some mocksv0.4.9 :: 20190527Add py37 support (including Travis workaround)Fix bug in content-length calculation (thanks @tim15)Replacefind_unused_portwith local function (thanks @schneideradam)Use black for formattingUpdateconfig-sample.txtfor changes inHomeAssistant
APIv0.4.8 :: 20180804Add.close()method toFauxmoPlugins, allowing for cleanup (thanks@howdypierce)discussion, e907245Append plugins directory tosys.pathfor more convenient loading of
additional modules (thanks@howdypierce)discussion, 03f2101Add HTTP headers to/eventservice.xmland/metainfoservice.xmlendpoints
5a53268v0.4.7 :: 20180512Minor dev-side changesUse pipenv for dev dependency managementAdd utf-8 to readme parsing (5 days ago) (thanks@hestela!)
49d2c57Change newline to\r\nin HTTP responses (thanks@GlennPegden2) 239bc79MatchMAN:case insensitive (thanks@wingett)
8307096Add GetBinaryState and GetFriendlyName commands including test cases (thanks@howdypierce!) 71392deMake comparison of the "SOAPACTION" header case-insensitive, per UPnP spec
(thanks@howdypierce!) a5cdf82Add fallback for determining IP address when DNS resolution is a problem
(thanks@howdypierce!) c2d7f13Bugfix: ~/.fauxmo/ not being read as a location for config file (thanks@howdypierce!) c322c9bv0.4.6 :: 20180212Mostly changes to try to fix compatibility with newer generation Echos / Echo
Plus, see #38v0.4.5 :: 20171114Support new GetBinaryState command (fixes n8henrie/fauxmo#31)v0.4.3 :: 20170914Add--versionto cliAddpython_requiresspecifier tosetup.pyBind to specific address inmake_udp_sock(fauxmo.utils), seems to fix
some intermittent failing tests on MacOS.v0.4.2 :: 20170601Add additional linters to testsSet reuseaddr and reuseport before binding socketv0.4.0 :: 20170402Rename handlers to pluginsAdd interface for user pluginsAdd type hintsRequire Python 3.6Eliminate third party dependenciesMake sure to close connection when plugin commands fail / return Falsev0.3.3 :: 20160722Added compatibility forrollershuttertohandlers.hassChangedhandlers.hassto send values from a dict to make addition of new
services easier in the futurev0.3.2 :: 20160419Update SSDPServer tosetsockoptto permit receiving multicast broadcastssockkwarg tocreate_datagram_endpointno longer necessary, restoring
functionality to Python 3.4.0 - 3.4.3 (closes #6)make_udp_sock()no longer necessary, removed fromfauxmo.utilsTox and Travis configs switched to use Python 3.4.2 instead of 3.4.4 (since
3.4.2 is the latest available in the default Raspbian Jessie repos)v0.3.1 :: 20160415Don't decode the UDP multicast broadcasts (hopefully fixes #7)They might not be from the Echo and might cause aUnicodeDecodeErrorJust search the bytes insteadTests updated for this minor changev0.3.0 :: 20160409Fauxmo now uses asyncio and requires Python >= 3.4.4Extensivechanges to codebaseHandler classes renamed for PEP8 (capitalization)Moved some general purpose functions tofauxmo.utilsmoduleBoth the UDP and TCP servers are now infauxmo.protocolsAdded some rudimentarypytesttests includingtoxandTravissupportUpdated documentation on several classesv0.2.0 :: 20160324Add additional HTTP verbs and options toRestApiHandlerand Indigo sample
to configNB:Breaking change:jsonconfig variable now needs to be eitheron_jsonoroff_jsonMakeRestApiHandlerDRYer withfunctools.partialmethodAddSO_REUSEPORTtoupnp.pyto make life easier on OS Xv0.1.11 :: 20160129Consolidate logger to__init__.pyand import from there in other modulesv0.1.8 :: 20160129Add the ability to manually specify the host IP address for cases when the
auto detection isn't working (https://github.com/n8henrie/fauxmo/issues/1)Deprecated theDEBUGsetting inconfig.json. Just use-vvvfrom now on.v0.1.6 :: 20160105Fix for Linux not returning local IPrestored method I had removed from Maker Musings original / pre-fork
version not knowing it would introduce a bug where Linux returned
127.0.1.1 as local IP addressv0.1.4 :: 20150104Fix default verbosity bug introduced in 1.1.3v0.1.0 :: 20151231Continue to convert to python3 codePulled in a few PRs by@DoWhileGeekworking
towards python3 compatibility and improved devices naming with dictionaryRenamed a fair number of classesAdded kwargs to several class and function calls for clarityRenamed several variables for clarityGot rid of a few empty methodsImport devices fromconfig.jsonand include a sampleSupportPOST, headers, and json data in the RestApiHandlerChange old debug function to use logging moduleGot rid of some unused dependenciesMoved license (MIT) info to LICENSEAdded argparse for future console scripts entry pointAdded Home Assistant API handler classUse "string".format() instead of percentLots of other minor refactoring