Caprice ceiling fan voice control - Part 2 of 2

The Mission

To enable voice control for the fans and lights of our new Mercator Caprice ceiling fans.
So we can say things like:
  • Alexa turn the office fan on/off
  • Alexa start/stop the office fan
  • Alexa turn the office fan to 80%
(The same commands can be used for the fan light)

The Steps

  • Step 1. Figure out the radio frequency (RF) commands for the fans
  • Step 2. Set up an RF sender on one of my Raspberry PIs
  • Step 3. Develop a script to control the fan
  • Step 4. Configure voice control via Alexa
Step 1 and 2 are covered here.

Step 3. Develop a script to control the fan

I use two scripts, available here.
send_rf.py     -- Handles sending the command to the RF sender on the Raspberry Pi
rf_control.py  -- Receives commands in the format rf_control.py <room> <cmd>.

For example: python rf_control.py office light

These scripts handle converting the room and command into the string of 0's and 1's, which are then broadcast.

Step 4. Configure voice control for Alexa

I use Openhab and NodeRed to manage my home automation.
For controlling the fans I've used NodeRed.

1. Install NodeRed

The NodeRed setup is long the lines of (untested):.
sudo apt-get install build-essential
sudo apt-get install -y nodejs python python-pip
sudo bash <(curl -sL https://raw.githubusercontent.com/node-red/raspbian-deb-package/master/resources/update-nodejs-and-nodered)

Then you should be able to access the nodered system on port 1880, e.g.
http://pi3.local:1880

2. Install Alexa-Local NodeRed plugin

This plugin allows you to add your own devices for control, emulating a Philips Hue device.
So the fans can be setup, and controlled using Philips Hue light commands.
i.e.
Alexa turn the office fan on
Alexa turn the office fan to 80%

From the hamburger menu icon go to "Manage Palette".
Then install the "node-red-contrib-alexa-local" node.

3. Configure the fans

Here's my fan config.

Add an Alexa device in NodeRed (such as "office light" shown above)

Once added (and your config is deployed) you can run device discovery from your Alexa Smart Home settings.



Your device should appear as shown to the left, and it's status will update in NodeRed.

Add a change node to set the fanname

This name is based to the "Choose command" node which does all the work.

Add a "Choose command" function node

This determines what command needs to be based to the fan.
msg.url = 'http://pi2:5000/fan/';
fanname=msg.fanname;
speed_var=fanname+'_speed';
if (msg.off) {  //Alexa stop the office fan
    msg.url += fanname+'/stop';
    global.set(speed_var,0);
    return msg;
}
if (msg.on_off_command) { //Alexa turn on|off the office fan
    if (msg.payload == 'on') {
        msg.url += fanname+'/s3';
        global.set(speed_var,3);
        return msg;
    }
    else {
        msg.url += fanname+'/stop';
        global.set(speed_var,0);
        return msg;
    }
}
speed = global.get(speed_var) || 3;
if (msg.change_direction > 0) { //Alexa speed up down the office fan
    //Increase
    if (speed < 6) speed++;
    msg.url += fanname+'/s'+speed;
    return msg
}
if (msg.change_direction < 0) { //Alexa slow down the office fan
    //Decrease
    if (speed > 1) speed--;
    msg.url += fanname+'/s'+speed;
    return msg
}
if (msg.bri > 0) { //Alexa change the office fan to 80%
    //Match speed
    speed = Math.floor(msg.bri/16);
    msg.url += fanname+'/s'+speed;
    return msg
}
return msg;

The "http request" node

This is just a GET and calls the url provided by the function above.

You could just use an exec node, if everything is on the same raspberry pi. e.g.
/bin/python /home/pi/scripts/rf_control.py


The web service uses python and flask. Here's the relevant code.
from flask import Flask
import rf.rf_control

app = Flask(__name__)
app.debug = True

@crossdomain(origin='*')
@app.route("/fan/<room>/<command>")
def fan_control(room, command):
    if (room == 'all'):
        for fan in ['office','master','fynn','connor','madi','guest']:
            rf.rf_control.do(fan, command)    
            time.sleep(2)
        return "Issued command "+command+" to "+room+" fans."
    elif (room == 'most'):
        for fan in ['office','master','madi','guest']:
            rf.rf_control.do(fan, command)    
            time.sleep(2)
        return "Issued command "+command+" to "+room+" fans."
    else:
        rf.rf_control.do(room, command)
        return "Issued command "+command+" to "+room+" fan."

if __name__ == "__main__":
    app.run(host='0.0.0.0')

The "On Error" Nodes

I've added some error logic that then has Alexa respond if there was an error.
This uses the Alexa plugin for OpenHab, but it's not required and I won't go into this.

4. Configure the Lights

Here is my NodeRed light configuration


It's very similar to the fan nodes. Here is the "light command" function.
lightOn = 0;
if (msg.payload == 'on') {
    lightOn = 1;
}
light_var=msg.fanname+'_light';
global.set(light_var, lightOn);
msg.url = 'http://pi2:5000/fan/'+msg.fanname+'/light';
return msg;


That's it!
Hopefully this helps you get your own fans automated.

Comments

Popular posts from this blog

Experience with Optus 4G wireless broadband

Port Forwarding on Optus 4G B525 router

Huawei B525 Python API