반응형

출처: https://jandh.tistory.com/16


아두이노와 ESP8266을 활용하여 센싱한 데이터의 데이터베이스 저장과 리트리빙

 

 

1.     사전 작업

 

WAMP 기반 웹서버를 Bitnami wordpress를 이용하여 구축한다. 물론 취향에 맞게 다른 AMP 스택을 설치할 수도 있다. 본 문서는 위의 Bitnami Wordpress를 기준으로 하여 설명한다.

Wordpress 설치 시에는 관리자id을 통상 admin으로 설정하는데, 해킹의 대상이 될 수 있으므로 가급적이면 다른 id로 설정하는 것을 권장한다.

 

Bitnami Wordpress를 설치한 후의 폴더 경로 및 구조는 아래와 같다.

 

 

<그림 1> Bitnami Wordpress 설치 폴더 구조

 

Wordpress는 아래와 같이 apps\wordpress 폴더에 설치가 되며, document root 는 htdocs이다.

 

<그림 2> Wordpress 설치 폴더

 

 

2.     센싱할 데이터 및 데이터베이스 테이블 정의

 

센싱하여 저장할 데이터는 센싱 시각, 온도 및 습도이며, mySql 기준으로 다음 [표.1]의 데이터 속성을 갖는다. DHT11 센서의 경우 온도, 습도를 정수형(TINYINT, SMALINT 등)으로도 선언 가능하겠으나, 확장성 등을 고려하여 FLOAT로 선언하였다.

여기서 sensDate는 편의상 실제로 측정한 시각이 아닌, 데이터베이스에 기록된 시각을 사용한다.

 

[표. 1] 데이터베이스 테이블 구조

Field

Data Type

Null

비고

sensDate

DATETIME

Not null

 

temperature

FLOAT

Not Null

 

humidity

FLOAT

Not null

 

 

 

3.     데이터베이스 생성

 

더 진행하기 전에 몇 가지 명칭을 아래와 같이 정의한다(실제 구현 시에는 다른 이름으로 설정하여 사용하여야 하며, 그렇지 않음으로 발생하는 손해는 사용자 개인 책임이다).

 

-       센싱한 데이터를 저장하기 위한 데이터베이스 이름 : abc_sens

-       데이터베이스의 테이블 이름 : sens_table

-       데이터베이스 사용자 : abc_user 

-       데이터베이스 사용자 비번 :  abc_1234

 

명령 프롬프트(cmd창)를 열고 <그림 1>의 mysql\bin 폴더로 이동하여 다음과 같이 root 권한으로 mysql을 실행한다. 이 때의 비번은 Wordpress 관리자 비번과 동일하다.

 

C:\Bit…\mysql\bin>mysql –u root -p

 

 

위에서 정의한 사용자 abc_user, 비번 abc_1234를 다음과 같이 생성한다.

 

mysql> create user ‘abc_user’@’localhost’ identified by ‘abc_1234’;

 

 

사용자를 생성하였으면 이번에는 데이터베이스를 생성한다.

 

mysql> create database abc_sens;

 

 

생성한 데이터베이스에 사용자가 액세스할 수 있는 권한을 아래와 같이 부여한다.

 

mysql> grant usage on *.* to 'abc_user'@'localhost';

 

아울러 사용할 데이터베이스인 abc_sens에 대한 모든 권한을 부여한다.

 

mysql> grant all on abc_sens.* to 'abc_user'@'localhost';

 

 

여기까지는 root 권한으로 mysql에서 작업을 한 것이다. exit 하고, 위에서 새로 생성한 사용자인 id는 abc_user, 비번은 abc_1234 로 mysql에 다시 접속한다.

 

>mysql –u abc_user –p (비번 입력 프롬프트가 나오면 비번인 abc_1234 입력)

 

이 상태에서 mysql> show databases; 명령을 입력하면 위에서 생성한 abc_sens가 나타난다. 이 데이터베이스를 사용한다는 선언을 mysql> use abc_sens; 입력으로 해준다.

 

 

 

이제 abc_sens 데이터베이스에 앞에서 정의한 테이블을 생성한다.

 

mysql> create table sens_table (sensDate DATETIME , temperature float, humidity float);

 

 

이상의 과정을 통하여 아래와 같이 테이블이 생성된 것을 확인할 수 있다.

 

mysql> describe sens_table;

 

 

이상을 확인하면 mysql을 빠져나온다.

 

 

4.     데이터 쓰기

 

4-1.      아두이노 ESP8266에서 웹서버로 데이터 보내기

 

아두이노에서 ESP8266의 AP 접속은 다음의 AT 커멘드를 순서대로 실행하여 완료한다. 여기서 AP_SSID와 AP_PWD는 ESP8266이 접속하고자 하는 AP의 SSID, password 이다. 각 AT 커멘드는 ESP8266 AT Instruction Set를 참조한다.

 

-       “AT+GMR\r\n”

-       “AT+CWMODE=1\r\n”

-       "AT+CWJAP=\"AP_SSID",\"AP_PWD\"\r\n"

 

위와 같이 AP에 접속한 후에는 다음의 명령을 실행한다.

 

-       "AT+CIPMUX=0\r\n"

 

 

데이터 센싱을 한 이후에, 그 센싱한 데이터를 웹서버로 전송하기 위하여 아두이노 프로그램에서 다음을 실행한다. 아래는 웹서버 IP주소가 192.168.5.4 이고, 웹서비스 포트가 80인 예이다.

 

-       "AT+CIPSTART=\"TCP\",\"192.168.5.4\",80\r\n"

 

이제 ESP8266의 AT커멘드로 웹서버로 전송할 데이터를 구성해본다. 앞에서 센싱한 온도가 20도, 습도가 30%라고 가정하면, AT+CIPSEND 명령으로 보낼 데이터는 다음과 같이 GET 방식을 이용하여 구성한다.

 

-       “GET /wordpress/abc-write.php?temprature=20&humidity=30\r\n”

 

여기서 /wordpress는 <그림. 2>의 htdocs가 위치한 경로명이고, abc-write.php는 htdocs에 위치한 데이터 저장을 위한 php 파일이다.

 

 

4-2.      데이터베이스에 저장하기

 

앞에서 웹서버가 수신한 데이터를 데이터베이스에 저장하기 위한 파일로 abc-write.php를 언급하였는데, 이 php 파일이 어떻게 코딩되는지 보기로 한다.

 

우선 데이터베이스를 액세스하기 위하여 다음의 각 변수를 지정한다. 각각의 변수에 해당하는 값들은 앞의 데이터베이스 생성에서 정의한 값들이다.

 

$servername = "localhost";

$username = "abc_user";

$password = "abc_1234";

$dbname = "abc_sens";

 

웹서버로 전송된 데이터는 parse_str() 함수로 파싱을 하고,

 

parse_str( html_entity_decode( $_SERVER['QUERY_STRING']) , $out);

 

temperature 인자가 있는 경우, mysqli() 함수를 이용하여 데이터베이스에 접속, insert into 명령으로 데이터를 기록하게 한다.

성공적으로 기록되면 리턴되는 값은 “Sensed data saved." 이고, 실패 시에는 "Error:”와 함께 에러 메시지를 리턴한다.

 

앞에서 설명했던 ESP8266을 통한 데이터 저장은 웹브라우저를 통해서도 확인이 되는데, 웹브라우저의 주소 창에 AT+CIPSEND로 전송될 데이터인 temprature=20&humidity=30 값을 이용하여, 다음과 같이 입력하면 그 결과를 확인할 수 있다.

 

-       http://192.168.5.4/wordpress/abc-write.php?temperature=20&humidity=30

 

<그림 3> 웹브라우저를 통한 데이터 전송

 

 

다음은 abc-write.php의 전체 코드이다.

 

<?php

  $servername = "localhost";

  $username = "abc_user";

  $password = "abc_1234";

  $dbname = "abc_sens";

  date_default_timezone_set('Asia/Seoul');

  $now = new DateTime();

  parse_str( html_entity_decode( $_SERVER['QUERY_STRING']) , $out);

  if ( array_key_exists( 'temperature', $out ) ) {

    // Create connection

    $conn = new mysqli($servername, $username, $password, $dbname);

    // Check connection

    if ($conn->connect_error) {

      die("Connection failed: " . $conn->connect_error);

    }

    $datenow = $now->format("Y-m-d H:i:s");

    $temp  = $out['temperature'];

    $humid = $out['humidity'];

    $sql = "INSERT INTO sens_table (sensDate , temperature, humidity) VALUES ('$datenow' , $temp, $humid)";

    if ($conn->query($sql) === TRUE) {

      echo "Sensed data saved.";

    } else {

      echo "Error: " . $sql . "<br>" . $conn->error;

    }

    $conn->close();

  }

?>

[Source Code] abc-write.php

 

 

4-3.      저장된 데이터 리트리빙하기

 

데이터베이스에 접근하기 이전에 wordpress 로그인 사용자를 확인하기 위하여

 

include_once("./wp-config.php");

$current_user = wp_get_current_user();

 

함수를 실행한다. 여기서는 로그인 하지 않은 경우에는 서비스를 거부하는 예로 코딩하였다. 즉, 현재 로그인 ID를 체크하여 로그인 사용자가 아니면 실행을 중단하도록 한다.

 

if( 0 == $current_user->ID )

 

로그인 사용자임이 확인되면, mysqli_connect() 함수를 이용하여 데이터베이스를 열고, mysqli_query() 함수를 이용하여 테이블의 데이터를 읽어 온다. 다음은 그 전체 소스코드이다.

 

<!DOCTYPE html><html>

<head>

<title>Sensed Data</title>

</head><body>

<center>

<H1>My Sensor Data</H1>

</center>

<?php

include_once("./wp-config.php");

$current_user = wp_get_current_user();

if( 0 == $current_user->ID ) {

        echo '<center>';

//      echo 'Login name is: ' . $current_user->display_name . '<br />';

        echo 'Login required... <br />';

        echo '</center>';

        exit();

}

echo "<center>";

echo "[" . $current_user->display_name . "() 로그인]<br />";

echo "</center>";

$con = mysqli_connect('localhost','abc_user','abc_1234','abc_sens');

// Check connection

if ($conn->connect_error) {

  die("Connection failed: " . $conn->connect_error);

}

//Selecting the data from table but with limit

$query = "SELECT * FROM sens_table order by sensDate desc LIMIT 0, 20";

$result = mysqli_query ($con, $query);

?>

<table align="center" border="0" cellpadding="3">

<tr><th>Send Date</th><th>Temperature(&deg;C)</th><th>Humidity(&#37;)</th></tr>

<?php

while ($row = mysqli_fetch_array($result)) {

?>

<tr align="center">

<td><?php echo $row['sensDate']; ?></td>

<td><?php echo $row['temperature']; ?></td>

<td><?php echo $row['humidity']; ?></td>

</tr>

<?php

};

?>

</table>

</body>

</html>

[Source Code] abc-read-text.php

 

 

다음의 그림은 위의 코드를 실행한 결과를 보여준다. 데이터가 많아서 페이지네이션이 필요한 경우에는 쿼리 문장에서 LIMIT 옵션을 이용하여 구현이 가능하다.

 

<그림 4> 데이터 리트리빙 결과

 

 

다음의 그림은 유사한 방법으로 Google Charts를 이용하여 그래픽으로 나타낸 것이다. 자세한 것을 아래의 소스코드 abc-read-chart.php를 참고한다.

 

<그림 5> Google Charts를 이용한 결과

 

<?php

// to check if user logged in

include_once("./wp-config.php");

$current_user = wp_get_current_user();

if( 0 == $current_user->ID ) {

        echo '<center>';

        echo '<h1>My Sensor Data</h1> <br />';

        echo '<p>Login required... <br /></p>';

        echo '</center>';

        exit();

}

// db initialization

$servername = "localhost";

$username = "abc_user";

$password = "abc_1234";

$dbname = "abc_sens";

date_default_timezone_set('Asia/Seoul');

// Check connection

$con = new mysqli($servername, $username, $password, $dbname);

if ($con->connect_error) {

  die("Connection failed: " . $con->connect_error);

}

?>

<!DOCTYPE HTML>

<html>

<head>

 <meta charset="utf-8">

 <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>

 <script type="text/javascript">

 google.charts.load('current', {packages:['corechart']});

 google.charts.setOnLoadCallback(drawChart);

 function drawChart() {

        var data = google.visualization.arrayToDataTable([

        ['Date', 'Temperature', 'Humidity'],

        <?php

        $query = "SELECT * From sens_table order by sensDate desc LIMIT 0, 200";

        $exec = mysqli_query($con,$query);

        while($row = mysqli_fetch_array($exec)){

               echo "['" . $row['sensDate'] . "'," . $row['temperature']. "," . $row['humidity']. "],";

        }

        ?>

        ]);

        var options = {

               title: 'Sensor Data',

               curveType: 'function',

               legend: {position: 'bottom'},

               hAxis: {direction: -1}

               }

               vAxis: {

                       viewWindow: {

                              min: -10

                       }

        };

        var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));

        chart.draw(data, options);

 }

 </script>

</head>

<body>

<center>

 <h1>My Sensor Data</h1>

 <div id="curve_chart" style="width: 1000px; height: 450px;"></div>

</center>

</body>

</html>

[Source Code] abc-read-chart.php

 

 

5.     결어

 

본 문서에서는 아두이노 보드와 ESP8266 WiFi모듈, 그리고 DHT11 온습도센서를 이용, 센싱한 온도와 습도를 네트워크로 전송하면 Bitnami Wordpress가 설치된 웹서버 데이터베이스에 데이터를 저장하고, 텍스트 모드로 출력하는 방법을 설명하였다. 아울러 구글 차트를 이용, 그래픽 모드로 리트리빙하는 방법도 설명하였다.


보안문제는 별도로 언급을 하지 않았으므로 본 문서를 참고로 하여 시스템을 시험 구축하고자 하는 사람은 보안에 대한 별도의 대책을 마련하여야 함에 유념하여야 한다.

 

[References]

 

[1] Bitnami Wordpress, https://bitnami.com/stack/wordpress

[2] ESP8266 AT Instruction Set Version 1.5.4, http://www.espressif.com/sites/default/files/4a-esp8266_at_instruction_set_en_v1.5.4_0.pdf

[3] Wordpress Code Reference, https://developer.wordpress.org/reference/

[4] PHP MySQL Improved Extension, http://php.net/manual/kr/book.mysqli.php

[5] Google Charts, https://developers.google.com/chart/

 



출처: https://jandh.tistory.com/16 [Inspiration]

반응형

+ Recent posts