3 releases
0.1.2 | May 15, 2020 |
---|---|
0.1.1 | Dec 9, 2019 |
0.1.0 | Dec 8, 2019 |
#643 in HTTP server
Used in rustmo-devices
36KB
707 lines
Rustmo - Talk to Your Code with Rust!
Rustmo is a library that allows for the creation of virtual devices which can be controlled (turned on or off) via Alexa-enabled things, such as the Amazon Echo Dot.
Rustmo is based on Fauxmo, and like Fauxmo, essentially emulates Belkin WeMo devices, backed by Rust code.
Rustmo simply emulates power "plugs". As such, virtual devices only have two states: On
and Off
.
Behind the scenes, Rustmo creates a SSDP listener
along with a webserver for each VirtualDevice
. Rustmo takes care of the details and all you need to do is implement
the VirtualDevice
trait to respond to Alexa requests.
Dependency
Declare a dependency on rustmo-server
:
[dependencies]
rustmo-server = "0.1.0"
Implement the VirtualDevice
trait
Secondly, create a struct that represents your device. Your "device" can be 100% pure code, or maybe it's a wrapper around a proprietary network protocol that controls a physical (but non-Alexa compatible) device somewhere on your network.
For examples of those, see the rustmo-devices crate for a few VirtualDevice
implementations that
attempt to control a Sony receiver, a Sony projector, and an Oppo DVD player.
Below is a simple, code-only example:
use rustmo_server::virtual_device::{VirtualDevice, VirtualDeviceError, VirtualDeviceState};
struct MyDevice {
state: VirtualDeviceState,
}
impl MyDevice {
fn new() -> Self {
MyDevice{
state: VirtualDeviceState::Off
}
}
}
impl VirtualDevice for MyDevice {
fn turn_on(&mut self) -> Result<VirtualDeviceState, VirtualDeviceError> {
eprintln!("Turning on");
self.state = VirtualDeviceState::On;
Ok(self.state)
}
fn turn_off(&mut self) -> Result<VirtualDeviceState, VirtualDeviceError> {
eprintln!("Turning off");
self.state = VirtualDeviceState::Off;
Ok(self.state)
}
fn check_is_on(&mut self) -> Result<VirtualDeviceState, VirtualDeviceError> {
eprintln!("Checking state");
Ok(self.state)
}
}
Create a RustmoServer, add a device
Next you need to create a RustmoServer
instance. It needs to listen on whichever
network interface your Alexa device is also connected.
Once created, you can add one or more VirtualDevice
implementations, which
makes them immediately discoverable by Alexa. And once discovered, immediately controllable.
use std::net::Ipv4Addr;
use std::str::FromStr;
use std::thread;
use rustmo_server::RustmoServer;
use crate::example::*;
fn main() -> std::io::Result<()> {
// create the rustmo server and start listening for SSDP discovery requests
let mut server = RustmoServer::new(Ipv4Addr::from_str("192.168.0.100").unwrap());
// add "My Device", making it controllable via Alexa on the specified port (1100)
let _my_device = server.add_device("My Device", 1100, MyDevice::new())?;
// wait forever
thread::park();
Ok(())
}
Various other helper methods exist for adding devices that need to poll for their state when changed, need to lie about their state when changed, combining devices into groups, etc.
Adding a VirtualDevice
returns a WrappedVirtualDevice
, which is your device instance wrapped in an
Arc<Mutex<Box<dyn VirtualDevice>>>
. This is the same type instance that RustmoServer
internally uses to respond
to Alexa requests. You're free to use this in other VirtualDevice
implementations that, perhaps, form more complex
operations across multiple devices and be guaranteed of thread safety when controlling the underlying device.
Note that each device needs a unique port number on which to listen for Alexa requests.
Talk to your VirtualDevice
via Alexa
Now that you've started a Rustmo server and added a device, you first need to ask Alexa to discover new devices.
Simply say: Alexa, discover devices
About 45 seconds later, Alexa should have found your device named "My Device"
.
Now you can ask Alexa to turn it on or off via commands like
Alexa, turn My Device on
Alexa, turn my device off
Note that the only commands Alexa knows how to send to Rustmo devices (which, again, are emulated Belkin WeMo power plugs) are 'On' and 'Off'. It's not possible to ask Alexa to do something specific with the device, such as "change channel" or "tell me the weather". These things need to happen via Alexa Skills, which is outside the scope of this project.
Some VirtualDevice
Implementation Notes
When you ask Alexa to turn a device on or off, it expects a response within 5 seconds. If Alexa doesn't receive a response in that amount of time it considers the device to be "not responding".
When a device's state is changed, Alexa immediately queries the device for its state (via VirtualDevice
's
check_is_on()
method). If the response to that query doesn't match what Alexa expects, Alexa will report that the
device "is malfunctioning".
Motivation
The motivation behind this project is to allow me to lose all the remote controls for my in-home movie theater.
Being able to turn everything on & off with one voice command, along with controlling other device-specific features via a custom mobile app, is a major qualify-of-life improvement for my 1%-er life.
Licensing
This code is licensed under the MIT license. Copyright 2019, ZomboDB, LLC.
Dependencies
~27MB
~547K SLoC