본문 바로가기

코딩/아두이노

아두이노 mySQL 접속

참고

github.com/ChuckBell/MySQL_Connector_Arduino/wiki

 

ChuckBell/MySQL_Connector_Arduino

Database connector library for using MySQL with your Arduino projects. - ChuckBell/MySQL_Connector_Arduino

github.com

준비사항

  • MySQL 서버 및 MySQL 사용자 수정 권한
  • 아두이노 보드
  • 이더넷 또는 와이파이 모듈

MySQL 서버 설정

아두이노 IDE에 라이브러리 추가

아두이노 IDE에 MySQL Connector Arduino 라이브러리를 추가한다.

외부 접속 설정

우선 아두이노에서 사용할 MySQL 계정을 다음 명령어로 손봐야 한다. 아두이노 보드가 어떤 IP로 접속할 지 정해지지 않았다면 1번을, 정해져있다면 2번을 root 계정으로 입력한다.

모든 IP 대역에서 허용

GRANT ALL PRIVILEGES ON *.* TO '아이디'@'%' IDENTIFIED BY '패스워드';

특정 IP 대역(예: 192.168.xxx.xxx)에서 허용

GRANT ALL PRIVILEGES ON *.* TO '아이디'@'192.168.%' IDENTIFIED BY '패스워드';

특정 IP(예: 192.168.0.17)에서 허용

GRANT ALL PRIVILEGES ON *.* TO '아이디'@'192.168.0.17' IDENTIFIED BY '패스워드';

아두이노 구현 예시

INSERT 예제

#include <Ethernet.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>

byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

IPAddress server_addr(192.168.0.17);  // IP of the MySQL *server* here
char user[] = "user";              // MySQL user login username
char password[] = "password";        // MySQL user login password

// Sample query
char INSERT_SQL[] = "INSERT INTO test_arduino.hello_arduino (message) VALUES ('Hello, Arduino!')";

EthernetClient client;
MySQL_Connection conn((Client *)&client);

void setup() {
  Serial.begin(115200);
  while (!Serial); // wait for serial port to connect
  Ethernet.begin(mac_addr);
  Serial.println("Connecting...");
  if (conn.connect(server_addr, 3306, user, password)) {
    delay(1000);
  }
  else
    Serial.println("Connection failed.");
}

void loop() {
  delay(2000);

  Serial.println("Recording data.");

  // Initiate the query class instance
  MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
  // Execute the query
  cur_mem->execute(INSERT_SQL);
  // Note: since there are no results, we do not need to read any data
  // Deleting the cursor also frees up memory used
  delete cur_mem;
}


SELECT 예제

#include <Ethernet.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>

byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

IPAddress server_addr(192.168.0.17);  // IP of the MySQL *server* here
char user[] = "root";              // MySQL user login username
char password[] = "password";        // MySQL user login password

// Sample query
char query[] = "SELECT population FROM world.city WHERE name = 'New York'";

EthernetClient client;
MySQL_Connection conn((Client *)&client);
// Create an instance of the cursor passing in the connection
MySQL_Cursor cur = MySQL_Cursor(&conn);

void setup() {
  Serial.begin(115200);
  while (!Serial); // wait for serial port to connect
  Ethernet.begin(mac_addr);
  Serial.println("Connecting...");
  if (conn.connect(server_addr, 3306, user, password)) {
    delay(1000);
  }
  else
    Serial.println("Connection failed.");
}


void loop() {
  row_values *row = NULL;
  long head_count = 0;

  delay(1000);

  Serial.println("1) Demonstrating using a cursor dynamically allocated.");
  // Initiate the query class instance
  MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
  // Execute the query
  cur_mem->execute(query);
  // Fetch the columns (required) but we don't use them.
  column_names *columns = cur_mem->get_columns();

  // Read the row (we are only expecting the one)
  do {
    row = cur_mem->get_next_row();
    if (row != NULL) {
      head_count = atol(row->values[0]);
    }
  } while (row != NULL);
  // Deleting the cursor also frees up memory used
  delete cur_mem;

  // Show the result
  Serial.print("  NYC pop = ");
  Serial.println(head_count);

  delay(500);

  Serial.println("2) Demonstrating using a local, global cursor.");
  // Execute the query
  cur.execute(query);
  // Fetch the columns (required) but we don't use them.
  cur.get_columns();
  // Read the row (we are only expecting the one)
  do {
    row = cur.get_next_row();
    if (row != NULL) {
      head_count = atol(row->values[0]);
    }
  } while (row != NULL);
  // Now we close the cursor to free any memory
  cur.close();

  // Show the result but this time do some math on it
  Serial.print("  NYC pop = ");
  Serial.println(head_count);
  Serial.print("  NYC pop increased by 12 = ");
  Serial.println(head_count+12);
}

설명

MySQL_Connection MySQL에 접속할 때 사용하는 클래스
MySQL_Cursor MySQL에 접속할 인스턴스를 지정하는 클래스
(MySQL_Connection).connect(서버IP, 포트, 계정명, 비밀번호) MySQL에 접속하는 함수 (boolean)
(MySQL_Cursor)->execute(쿼리구문) MySQL 구문을 실행(=전송)하는 함수 (boolean)
column_names MySQL 데이터의 각 열의 목록을 저장하는 자료형
(MySQL_Cursor)->get_columns() 해당 MySQL 인스턴스에서 각 열을 가져옴. (column_names)
row_values DB의 특정 열에서 각 행에 따라서 정보를 저장하는 자료형
(MySQL_Cursor)->get_next_row() DB에서 행을 하나씩 가져와 저장하는 함수(row_values)
(MySQL_Cursor)->close() 해당 인스턴스를 삭제하는 함수(void)

주의사항

MySQL의 외부접속을 허용하게 되면 보안상 상당히 취약해질 수 있다. 따라서 fail2ban같은 도구를 활용해 서버의 보안을 조금이라도 확보해야 한다.