Making A Home Automation Backend with FlashLex

May 04, 2019

pr_02c876b3

Making a home automation system shouldnt give a giant or foriegn company information on how my home works. I also want something hackable and based on "off the shelf" components like Raspberry Pi. This project lets you put a home automation system on the internet securely with a DIY, using the FlashLex IOT platform.

sonoff arch

Architecture Elements

  • FlashLex API - Cloud platform to route messages to your thing.
  • The Thing - Your Raspberry PI IOT Device

    • FlashLex SDK App - Python service that will take messages from the thing's topic and store them locally.
    • Sonoff Switch App - Python service that listens to messages and will execute Sonoff commands by device name, also schedules commands to items.
  • Sonoff WIFI Switch - Independent In Line switches that are individually addressable on a local wifi network

Steps for Tasmota Installation

This isnt a Tasmota installation tutorial, there are tons of links above to get going on that. This is a cookbook for enableing your home automation hub to be a FlashLex device, so we will limit the instructions to that.

Important Links

Using esptool to flash Tasmota

Remember to hold the button down on the sonoff to put it in firmware update mode.

python3 -m venv ./venv
source venv/bin/activate
python
pip install esptool
pip install --upgrade pip
esptool.py -h
ls -l /dev/tty.usb*
esptool.py -p /dev/tty.usbserial-A50285BI write_flash -fs 1MB -fm dout 0x0 sonoff_6_6_0.bin

Installing the FlashLex Service

All the FlashLex projects rely on the FashLex SDK, which collects messages from the gateway using a locally running Python service. More information on installing the FlashLex service can be found in the FlashLex Docs.

Installing FlashLex SDK

The Sonoff Scheduler Hub Backend

Devices are managed and scheduled by code on the your FlashLex thing that sends commands to the individual sonoff switches over wifi. Essentially the sonoff switch software both automates scheduling of commands as well as provides a message manager for sending commands to your sonoff switches.

Sonoff Switch Commands

Message Syntax Sonoff Syntax Description
on Power%20on Turn the switch on.
off Power%20off Turn the switch off.
toggle Power%20TOGGLE Toggle the switch state.

Sonoff Scheduler Links

The Scheduler Config

For each switch that your scheduler will control provide an entry and the the schedule as well as the command you would like to send.

devices:
  - name: living-room 
    ip: 192.168.5.59
    schedule:
      - time: "21:06"
        command: Power%20off
      - time: "21:08"
        command: Power%20on

Creating the Scheduler Job

This project uses the python scheduler for automation. This allows for the creation of simple jobs that can send commands to the sonoff switches over HTTP.

    for device in config['devices']: 
        for schedule_item in device['schedule']:
            schedule.every().day.at(schedule_item['time']).do(sonoff_job, 
                ip_addr=device['ip'], sonoff_command=schedule_item['command'])

https://github.com/claytantor/sonoff-switch/blob/master/app.py#L66

and the job:

def sonoff_job(ip_addr, sonoff_command):
    print("setting {0} to {1}".format(ip_addr, sonoff_command))
    r = requests.get('http://{0}/cm?cmnd={1}'.format(ip_addr, sonoff_command))

https://github.com/claytantor/sonoff-switch/blob/master/app.py#L40

You can learn alot more about how to ticker with the Tasmota/Sonoff on the internet: https://lmgtfy.com/?q=sonoff+tasmota

Creating the FlashLex Listener Job

Now that you have a home automation framework in place, all you need to do is add a job that listens to your thing's MQTT queue and can route control commands to the switches.

def flashlex_job(config):

    lookup = {
        "on": "Power%20on",
        "off": "Power%20off",
        "toggle": "Power%20TOGGLE"
    }

    sdk = FlashlexSDK(config)
    records = sdk.getSubscribedMessages()

    # process new messages
    for record in records:
        #print("record", record)
        #print("payload message", record['message']['payload']['message'])

        payload_message = record['message']['payload']['message']

        ## find the ip address
        result = list(filter(lambda x: (x['name'] == payload_message['device']), config['devices']))

        
        for device in result:
            ## find the command
            r = requests.get('http://{0}/cm?cmnd={1}'.format(device['ip'], lookup[payload_message['value']]))

        sdk.removeMessageFromStore(record)

https://github.com/claytantor/sonoff-switch/blob/master/app.py#L11

now you can add the scheduled job listener to your automation:

#schedule flashlex to accept commands 
schedule.every(10).seconds.do(flashlex_job, config=config)

Creating the sonoff-switch service

You will want to have your sonoff switch runinng as a service so that even if your Raspberry Pi restarts it will come back up. To enable your sonoff-switch hub to run as a service install the service file and enable the service with systemctl.

$(pwd)/venv/bin/python3 makeservice.py -d $(pwd) -t sonoff.service.mustache > sonoff.service

Instructions for setting up your service can be found at https://www.raspberrypi-spy.co.uk/2015/10/how-to-autorun-a-python-script-on-boot-using-systemd/

sudo cp sonoff.service /lib/systemd/system/sonoff.service
sudo chmod 644 /lib/systemd/system/sonoff.service
sudo systemctl daemon-reload
sudo systemctl enable sonoff.service

Sending Messages with FlashLex

You can use FlashLex to send control messages to your hub devices by name. Just send a message to your FlashLex Enabled device with the message schema.

curl -X POST \
  https://api.flashlex.com/prd/v1/things/5da91b24-28f2-4b55-829e-26528ba7a2eb/publish \
  -H 'Accept: */*' \
  -H 'Accept-Encoding: gzip, deflate' \
  -H 'Authorization: Bearer eyJraWQiOiJvQndJY0pCXC92Mzg3T3JaK2ZGMVVETjNONlNGM3ZQQkg5eWl1VTMzbXdKdz0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIzNjE4MDQ1NS1hNTlhLTQxY2MtODNiYi1jYzZiNDEyN2I0YzMiLCJkZXZpY2Vfa2V5IjoidXMtZWFzdC0xXzQ0MGFiZDk0LTM1OGItNDdlNi1iYWFlLWUyZGU1ODJkNzExNiIsImV2ZW50X2lkIjoiYzYxMWJkOTgtODNmMy00NzlmLWI2MzktODk1YTAyMDkyYzhlIiwidG9rZW5fdXNlIjoiYWNjZXNzIiwic2NvcGUiOiJhd3MuY29nbml0by5zaWduaW4udXNlci5hZG1pbiIsImF1dGhfdGltZSI6MTU3NTI1ODMzNiwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tXC91cy1lYXN0LTFfUFVrVTdya0VQIiwiZXhwIjoxNTc1MjYxOTM2LCJpYXQiOjE1NzUyNTgzMzYsImp0aSI6IjlkODcwMDk5LWRjYzUtNGEwYy1iMjFkLTJkNTc1NzNhNmEzYyIsImNsaWVudF9pZCI6IjUycXZwcTRnNGZyMzFoOXIwMmNmbmlqZjcxIiwidXNlcm5hbWUiOiJjbGF5dGFudG9yQGdtYWlsLmNvbSJ9.Bgrx2LCv7fR-44qPbfRLqggAVRvZIwLZ0j8qP8TpzZXTKXhWZqoD7IHTzG4a-Ahv1AKANq99m-yb8EbfPZ1vutyPq8WCo8zDrlRjrBi3FNv0G1hIfy5-jJ1TVINdvLwFMpUQ_35LaN6UqU3sP00gYljgm1CydirhoLhvLFhcvomqqX_foCuKy1sGYM8gQFtEZIL7IJVkDiyHgND-DeFl6FDbfiDPBqhmHJE8i5XF-IMuL5jCOR7A610ZxUprg4_mR3TvUlhMTD4lp-prl2R7CNIeiaGfqgNNrey5wchDMpezc9oqmeoDneRtCqHUNBqm_hYSenyt_T_8wNmAV-sXPQ' \
  -H 'Content-Type: application/json' \
  -d '{"device": "bedroom-01-tv", "action": "switch", "value": "toggle"}'

For more information on setting up the FlashLex SDK on your IOT device check out the SDK documentation at: http://docs.flashlex.com.s3-website-us-east-1.amazonaws.com/flashlex-docs/v1.5/sdk/index.html