자 이제 본격적으로 스마트홈 구축을 위한 프로그래밍을 진행해보자. 앞에서 언급했던 것 처럼 파이썬은 지그비 통신을 활용하여 온습도 데이터를 수신받아 데이터베이스화 할 것이며 PHP로 구축된 웹페이지에서 이 DB를 활용하여 차트로 도식화 한다. 이러한 프로그램 각각의 역할과 코드의 기능에 대해 정확히 알고 있어야 본 예제를 입맛에 맞게 수정하거나 응용할 수 있으므로 모쪼록 잘 이해하고 넘어가주길 바란다.



1. MySQL


MySQL을 다루려면 기본 SQL(Structured Query Language) 명령어를 어느정도 숙지하고 있어야 한다. 여기서 SQL은 데이터베이스의 자료를 검색하고 추가및 삭제 등의 조작을 할 수 있도록 고안된 컴퓨터 언어이다. 사람이 사용하는 언어와 문법 자체가 비슷하기 때문에 이해하기 쉽고 사후 관리도 편리하다. 또한 Query 라는 이름에서도 알 수 있듯이 검색 부문에 특화되어있는 데이터베이스이다.


구조 자체가 어렵진 않으니 여기서는 간단히 사용되는 명령어만 서술할 것이며 자세한 내용은 인터넷 상에 자료가 많으므로 검색해 볼 것을 추천한다.


  # MySQL 접속

mysql -u user -p password


위에서 user 부분은 사용자명을 뜻하며 따로 설정을 하지 않았다면 기본값인 root를 적어주며 password 부분은 MySQL을 설치할 때 생성한 비밀번호를 적어준다.


# 데이터베이스 생성

  CREATE DATABASE db_name;


# 데이터베이스 목록 표시

SHOW DATABASES;


# 데이터베이스 사용

USE db_name;


# 테이블 생성

  CREATE TABLE table_name(ddate datetime, zone text, temp float, humi float);


# 테이블 목록 표시

SHOW TABLES;


# 테이블 구조 표시

DESCRIBE table_name;


위 명령어 들을 사용해보면 데이터베이스를 만들거나 관리하는 것이 그렇게 어려운 부분이 아니라는 것을 알게 될 것이다. 자세한 설명은 생략하며 아래처럼 테이블까지 만들어서 파이썬을 통해 데이터베이스에 현재 시간과 장소, 온습도 데이터를 넣을 준비를 하자. 필자는 db의 이름을 testdb, 테이블의 이름을 tempdata로 지정했으며 다른 이름을 사용해도 무방하다.




2. Python


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import serial
import MySQLdb
import datetime
 
# Xbee 모듈과 시리얼 통신
port = serial.Serial("/dev/ttyAMA0""9600")
 
# MySQL 접속
db = MySQLdb.connect("localhost""User_name""User_password""testdb")
curs = db.cursor()
 
ZONE = "HOUSE"
print 'Start Monitor'
 
while True:
        try:
            # 지그비 통신을 통한 데이터 수신
            data = port.readline()
 
            print("House temp/humi is ")
            print(data)  
 
            # 수신한 데이터와 현재 시간 및 장소를 SQL 쿼리문으로 전송
            curs.execute("""INSERT INTO tempdata (ddate, zone, temp, humi) VALUES (%s,%s,%s,%s)""",
                (datetime.datetime.now().strftime('%Y-%m-%d %H:%M'), ZONE, data.split(',')[0], data.split(',')[1].strip()))
            db.commit()
 
        except KeyboardInterrupt:
                break
 
port.close()
db.close()

cs


파이썬 코드의 경우 먼저 지그비 통신을 하기 위해 Xbee 모듈과 시리얼로 연결된다. 그리고 MySQL에 접속하여 수신 받은 데이터를 SQL 쿼리문 형태로 전송하여 앞서 생성한 DB에 데이터를 입력하게된다. 제대로 동작한다면 다음과 같이 1분마다 DB에 데이터가 입력되는 것을 볼 수 있다.




3. Highcharts


다음은 저장된 DB를 가지고 그래프로 출력하는 법을 알아보겠다. 사실 DB와 연동하여 PHP 만으로도 꽤나 괜찮은 그래프를 만들어볼 수 있긴 하지만 여기서는 그보다 간단하면서 깔끔하게 나타낼 수 있는 오픈소스를 사용해보자. 차트를 만들어 볼 수 있는 오픈소스로는 Google chart나 Nwagon, chart.js 등의 다양한 종류가 있으며 여기서는 개인 홈페이지에서는 무료로 사용할 수 있으며 모바일 부분도 잘 지원해주는 highchart 소스를 활용할 것이다. 


주소는 다음과 같으며 해당 소스를 다운로드한 후 라즈베리파이의 웹서버 경로인 /var/www/html 에 압축을 풀어주면 된다.



http://www.highcharts.com/



4. PHP + HTML


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php
 
// PHP 에러 코드 확인
ini_set('display_errors''On');
error_reporting(E_ALL|E_STRICT);
 
// MySQL 접속
$mysql_host = 'localhost';
$mysql_user = 'User_name';
$mysql_password = 'User_password';
$mysql_db = 'testdb';
$conn = @mysql_connect($mysql_host$mysql_user$mysql_password);
$dbconn = mysql_select_db($mysql_db$conn);
 
// DB에서 원하는 데이터 검색
$sql="
select * from (
SELECT DATE_FORMAT( ddate,  '%m-%d %HH' )  mdh , COUNT( * ) cnt, SUM( temp ) , 
round(SUM( temp ) / COUNT( * ),1)  atemper, round(SUM( humi ) / COUNT( * ),1)  ahumier
FROM  `tempdata`
GROUP BY DATE_FORMAT( ddate,  '%Y%m%d%H' )
order by ddate desc
limit 12
) t_a
order by t_a.mdh
";
 
$result = mysql_query($sql) ;
 
$str_mdh="";
$str_atemper="";
$str_ahumier="";
 
// 온습도 문자열 연결
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
 $str_mdh .="'".$row['mdh']."',";
 $str_atemper .="".$row['atemper'].",";
 $str_ahumier .="".$row['ahumier'].",";
}
 
// 오른쪽 공백 제거
$str_mdhsubstr($str_mdh,0,-1);
$str_atempersubstr($str_atemper,0,-1);
$str_ahumiersubstr($str_ahumier,0,-1);
 
?>
cs


highchart 웹페이지에서 예제 소스를 보면 아래 HTML 코드의 xAxis-categories 부분에 시간이나 날짜가, series-data 부분에 y축을 나타내는 데이터가 각각 쉼표와 함께 들어간다는 사실을 알 수 있을 것이다. 따라서 차트를 따라 그리려면 데이터가 알맞게 들어갈 수 있도록  PHP 코드상에서 한 문자열로 만들어주어야 한다. 


위 코드는 이러한 방식을 구현한 코드로서 select 문을 통해 db에서 데이터를 순서대로 가져온 후 while 문을 통해 각각의 날짜와 시간을 변수 str_mdh에 저장한다. 또한 온도와 습도 데이터는 변수 str_atemper와 str_ahumier 에 쉼표와 함께 한 문자열로 연결하고 최종적으로 뒤의 공백을 제거함으로서 완성한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!DOCTYPE HTML>
<html>
<head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>House Monitor</title>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
        <style type="text/css">${demo.css}</style>
        <script type="text/javascript">
 
$(function () {
    $('#temp').highcharts({
        chart: {
            type: 'line'
        },
        title: {
            text: 'Temperature'
        },
        subtitle: {
            text: 'http://creamp.tistory.com'
        },
        xAxis: {
            categories: [<?php echo $str_mdh?>]
        },
        yAxis: {
            title: {
                text: 'Temperature (°C)'
            }
        },
        plotOptions: {
            line: {
                dataLabels: {
                    enabled: true
                },
                enableMouseTracking: false
            }
        },
        series: [{
            name'HOUSE',
            data: [<?php echo $str_atemper?>]
        }]
      });
    $('#humi').highcharts({
        chart: {
            type: 'line'
   },
        title: {
            text: 'Humidity'
        },
        xAxis: {
            categories: [<?php echo $str_mdh?>]
        },
        yAxis: {
            title: {
                text: 'humidity (%)'
            }
        },
        plotOptions: {
            line: {
                dataLabels: {
                    enabled: true
                },
                enableMouseTracking: false
            }
        },
        series: [{
            name'HOUSE',
            data: [<?php echo $str_ahumier?>]
        }]
    });
});
        </script>
</head>
<body>
        <script src="https://code.highcharts.com/highcharts.js"></script>
        <script src="https://code.highcharts.com/modules/exporting.js"></script>
        <div id="temp" style="width: 900px; height: 440px; margin: 30px auto"></div>
        <div id="humi" style="width: 900px; height: 440px; margin: 30px auto"></div>
</body>
</html>
cs




5. 결과 화면


이제 모든 과정이 완료되었다. 라즈베리파이의 웹서버에 접속하여 위와 같은 화면이 제대로 나오는지 확인해보자.