2016년 3월 27일 일요일

샤오미 체중계 (xiaomi scale) 를 사용한 스마트홈 만들기 - 5탄 (Smart Mirror 와 Mi Scale 연결!)

Mi scale 통신도 됐고 Smart Mirror 도 얼추 정리가 되었는데, 문제는 node.js 로 되어 있는 smart mirror 와 python 으로 동작하는 scale.py 를 어떻게 연결 하느냐 였다.

출입자가 체중계에 올라가면 몸무게를 smart mirror 에게 보내서 profile 을 결정해야 하는데 python 도 node.js 도 익숙치 않은 나에게는 난감하기 짝이 없는 과제였다. 그런데 상식적으로 생각해 보면 RPC (Remote Procedure Call) 이지 않을까 생각해서 rpc 를 검색어로 구글링 했더니 역시나 simple 한 솔루션이 있었다.

이름하야 'zerorpc'
zerorpc 의 한 줄 설명으로 내가 풀어야 하는 숙제에 대한 희망이 생겼다.

"An easy to use, intuitive, and cross-language RPC"


사이트를 방문해 보면 알겠지만, 설치나 사용 방법이 엄청 간단하다.
python 을 위해서는 'pip install zeropc'
node.js 를 위해서는 'npm install zeropc'
로 모든 준비가 끝이다.

소스 코드는 Server / Client 로 구현해야 하는 부분이 있는데 내 상황에는 node.js 가 Server 이고 python 이 client 이므로

[Server - node.js]
var zerorpc = require("zerorpc");
var server = new zerorpc.Server({
    hello: function(name, reply) {
        reply(null, "Hello, " + name);
    }
});
server.bind("tcp://0.0.0.0:4242");
[Client - python]
import zerorpc
c = zerorpc.Client()
c.connect("tcp://127.0.0.1:4242")
print c.hello("RPC")
위 코드들만 smart mirror 와 scale.py 에 삽입 해 주면 끝이다.

그럼 세부적인 설명을 더하면,
smart mirror 의 js 중 ScaleService.js 를 추가 해 주고, controller.js 에서 호출 해 준다.

controller.js 코드 먼저 살펴 보면,
데모에 수고해 준 멍멍이와 BABY 인형의 몸무게를 5.5 kg, 8.4 kg 이라고 할 때 대충 이런 구현이 가능하다. 만약 Profile 범위 밖의 몸무게가 감지 되었다면 침입자로 통보를 해도 될 것 같다.
diff --git a/js/controller.js b/js/controller.js
index ad55e15..f8f4c6f 100644
--- a/js/controller.js
+++ b/js/controller.js
@@ -5,6 +5,7 @@
             AnnyangService,
             GeolocationService,
             WeatherService,
+            ScaleService,
             MapService,
             HueService,
             CalendarService,
@@ -50,8 +51,17 @@
             restCommand();

             var refreshMirrorData = function() {
+                ScaleService.init();
+                $rootScope.$on("ScaleService:scale", function (event, data) {
+                    if(scale > 5 && scale < 6)
+                        $scope.greeting = "안녕~ 멍멍아";
+                    if(scale > 8 && scale < 9)
+                        $scope.greeting = "하이 BABY~ ";
+                    else
+                        $scope.greeting = "누구세요?";
+                });
+
                 //Get our location and then get the weather for our location
                 GeolocationService.getLocation({enableHighAccuracy: true}).then(function(geoposition){
+
                     console.log("Geoposition", geoposition);
                     WeatherService.init(geoposition).then(function(){
                         $scope.currentForcast = WeatherService.currentForcast();
$rootScope.$on 부분이 ScaleService 로 부터 온 event 를 받아서 몸무게를 비교하는 부분이다.


다음은 ScaleService.js 의 구현,
(function() {
    'use strict';

    function ScaleService($rootScope) {
        var service = {};
        service.init = function() {
            var zerorpc = require("zerorpc");
            var server = new zerorpc.Server({
                hello: function(scale, reply) {
                    $rootScope.$emit("ScaleService:scale", scale);
                    reply(null, "Hello, " + scale);
                }
            });
            server.bind("tcp://0.0.0.0:4242");
        };
        return service;
    }
    angular.module('SmartMirror')
        .factory('ScaleService', ScaleService);
}());

마찬가지로 $rootScope.$emit 이 controller 에게 측정된 scale.py 로 부터 측정된 몸무게를 받아서 event 로 넘겨 주는 부분이다.

간단하지 아니한가!

마지막으로 scale.py 를 살펴 보자. (full source 코드는 이전편에서 소개 되었으니 참조)
...
if unit:
print("measured : %s %s" % (measured, unit))
c = zerorpc.Client()
c.connect("tcp://127.0.0.1:4242")

print c.hello(measured)
else:
print 'scale is sleeping'
...
위의 3줄 추가로 client 의 구현도 마무리 되었다.

이로써 Smart Mirror 와 Mi Scale 의 연결이 마무리 되었다. 이제 가족들의 몸무게를 관리 해 주는 Profile 부분만 추가 해 주면 출입자 인식 시스템은 완성 될 것 같다. 기어 S2 로 문 여는 것도 참 유용하게 쓰고 있는데 이것도 어서 이쁘게 설치해서 써봐야 겠다.

그럼.. 시연 영상을 볼까.. 출연에는 멍멍이와 BABY 가 수고해 줬다. 멍멍이는 출연료라도 챙겨 줘야 할텐데.. 이참에 목욕이나 시켜줄까....... ^^ 애들이 너무 가벼워서 몸무게를 늘리기 위해 CD 케이스가 협찬을 했다.



댓글 없음: