project sunrise - 04-30-20

Project Name: Sunrise

Goal: Provide a sunrise via synchronised iot lights

What we achieved: Controlling a single light via secure webapp

Repo: https://gitlab.com/BTBTravis/sunrise

Sunrise, a really fun project to control IOT lights. Teamed up after several years once again Steven and I united powers to make something for this the April 2020 Rokkin Cat Hank and Tell. We learned a good deal along the way and ended up with something half way functional.

The two main technologies were python+flask and typescript+react. We used the hackathon to learn more about authentication on the flask side and react contexts + carbon components. Following some examples from the flask documentation we were able to pretty rapidly secure the app. Here is an expert of our router.py. Using python decorators and flasks built in session functionality authed endpoints need only have a @authed.

user_key = os.environ['USER_SECRET_KEY']

def authed(f):
    @wraps(f)
    def wrap(*args, **kwargs):
        if ('key' not in session or session['key'] != user_key):
            return ("no key", 401)        # get user via some ORM system
        return f(*args, **kwargs)
    return wrap

@app.route('/api/v1/on', methods=['POST'])
@authed
def on():
    device = request.get_json()
    success = tplink.turn_device_on(device, session['tp_token'])
    return ({ 'success': success },200)

On the react side we kept things wimple with no redux and just a shared context.

From frontend/src/components/DemoDeviceList.tsx

import React, { useEffect, useContext } from 'react';
import { getDevices, Device, turnOnDevice } from '../hooks/backendAdapter'
import { DevicesContext } from '../hooks/deviceContext';

const DemoDeviceList: React.FC = () => {
    const { state, setDevices, turnOn } = useContext(DevicesContext);
    useEffect(() => {
        getDevices().then((devices) => {
            setDevices(devices);
        });
    }, []);

    const {devices} = state;

    const handleDeviceClick = (d: Device) => () => {
        turnOnDevice(d).then(() => turnOn(d));
    }

    return (
        <ul>
            {devices.map(d => <li onClick={handleDeviceClick(d)} key={d.device_id}>{d.name}</li>)}
        </ul>
    ...

Using components from IBM’s carbon react component library was easy. It yielded nice results and I’d consider using it for more side projects.

carbon in action

carbon in action

The best part was sharing in the excitement of turning on a light in a friends house from around the world and seeing it on webcam.

tags: [tech] [python] [react]