본문 바로가기

아는 만큼 보인다/AWS

AWS IoT Button 으로 LIFX 스마트 전등 제어하기

결과 영상

제어 흐름도

실습 의의

  • LIFX bulb가 제공하는 자체 모바일용 앱을 사용하는 것 만으로, 
    • 전등의 색, 밝기, 효과 등을 재미나게 적용할 수 있습니다. 
    • 예약 기능까지 제공하여 모바일 앱을 유용하게 사용가능합니다.
  • 그럼에도 굳이 AWS IoT Button 연동하려는 이유는
    • 모바일 폰 없을 때 버튼 동작으로 간단하게 on/off
    • 아마존 IoT 서비스 적용 방법 학습

사전 준비물

실습 하기

  1. LIFX 전구 설정 
    1. 스카트폰에서 LIFX 앱 설치 후, 전구 추가
    2. 참고: https://support.lifx.com/hc/en-us/articles/204538340-LIFX-Bulb-Setup

  2. LIFX 전구 api key 생성: https://api.developer.lifx.com/docs/how-to-use-the-following-examples

  3. AWS IoT & Lambda 설정
    * 참고: https://docs.aws.amazon.com/iot/latest/developerguide/iot-button-lambda.html 
    * AWS > Lambda > Create Lambda > blueprint:iot-button > 이후 아래 화면의 Wizard를 따라 함
    * Wizard 사용시, AWS IoT에 Thing, Polity, Certificate가 자동으로 생성됨

  4. IoT Button 설정
    * AWS IoT가 생성한 Certificate를 저장하고, AWS IoT의 endpoint 를 설정함

  5. AWS Lamabda 함수 작성 (myLifxBulb)
  6. var https = require('https');
    
    // LIFX Configurations
    //
    // LIFX API host.
    var gApiHost = 'api.lifx.com';
    
    // LIFX API key ---> refer to https://api.developer.lifx.com/docs/how-to-use-the-following-examples
    var gLifxApiKey = 'replace-to-your-Api-Key';
    var gSelector = 'all';
    var gStateLong = {"power": "off",  "duration" : 0};
    var gStateSingle =
                {
                    "power": "on",
                    "brightness": 1,
                    "color": "white",
                    "duration" : 0
                };
     var gStateDouble = {
                    "power": "on",
                    "brightness": 0.5,
                    "color": "green",
                    "duration" : 0
                };
    
    function getRequestOptions(reqPath, reqMethod, reqContentLength)
    {
        var reqheaders =
        {
            'Accept':   '*/*',
            'Authorization': 'Bearer ' + gLifxApiKey,
            'content-type': 'application/json',
            'content-length': reqContentLength
        };
        
        
        var options = 
        {
            host:       gApiHost,
            path:       reqPath,
            method:     reqMethod,
            headers:    reqheaders
        };
        //console.log("LIFX request options: ", options);
        return options;
    }
    
    function setState(requestData, callback)
    {
        var options = getRequestOptions('/v1/lights/' + gSelector + '/state', 'PUT', Buffer.byteLength(requestData));
        
        console.log('Try to call https://' + options.host + options.path);
        console.log('Request Data = ', requestData);
        
        // Create the HTTP request and 
        // make the API call.
        var req = https.request(options, function(res) 
        {
            // Log the status code...
            console.log('setState(): Status Code = ', res.statusCode);
            var responseBody = '';
            res.setEncoding('utf-8');
            res.on('data', function(data)
            {
                console.log('response body: ' + data);
                responseBody += data;
            });
            res.on('end', function()
            {
                // Any result in 2xx is OK.
                if (res.statusCode >= 200 && res.statusCode <= 299)
                {
                    console.log('setState() was successful.');
                    callback(true, responseBody);
                } 
                else
                {
                    console.log('setState() was failed.');
                    callback(false, responseBody);
                }
            });
        }).on('error', function(e)
        {
            console.log('setState() failed: '+ e.message);
            callback(false, 'setState() failed: '+ e.message);
        });
        
        req.write(requestData);
        req.end();
    }
    
    exports.handler = function(event, context)
    {
        console.log('Called handler()');
        console.log('ClickType: ' + event.clickType);
        //////////////////////////////
        // Check the click type 
        var state;
        switch(event.clickType)
        {
            case "SINGLE":
                state = gStateSingle;
                break;
            case "DOUBLE":
                state = gStateDouble;
                break;
            
            case "LONG":
                state = gStateLong;
                break;
            default:
                console.log('Unknown clickType: ' + event.clickType);
                context.fail('Unknown clickType: ' + event.clickType);
                return;
        }
        var requestData = JSON.stringify(state); 
        setState(requestData, function(result, responseBody)
        {
            if (result)
            {
                // The process completed successfully.
                console.log('The process completed successfully.');
                context.succeed(responseBody);
            }
            else
            {
                // The process failed; check the log for details.
                console.log('The process completed with errors.');
                context.fail(responseBody);
            }
        });
    };

    AWS IoT 수정 (Rule engine)

관련 사이트