[PJT] AWS & DB

정재훈·2022년 5월 23일
0

간단 PJT

목록 보기
4/6

AWS 셋팅

이름, APP(Quick Start를 통한 생성), 키페어 생성(유출 조심), 스토리지 설정(프리 티어는 30GB까지 무료) 등을 모두 해줍니다.

인스턴스 ID를 클릭을 통해 추가 셋팅을 해줍니다.
퍼블릭 IPv4 주소에 접근가능한다.

포트 개방

DataBase를 사용하기 위해 포트를 개방시켜줘야 합니다.

보안 > 보안그룹 > 인바운드 규칙 편집 > 규칙 추가에서 ICMP와 mySQL 포트 개방하기!
인바운드 : 외부에서 서버로 들어오는 신호를 허용할지 말지 결정하는 보안 규칙
ICMP : 서버가 정상적으로 동작되는지 확인하기 위해 Ping을 날리는 행위
0.0.0.0/0 : 어떠한 IP라도 접속 허용하겠다는 IP
mysql 포트 : 3306

우분투 기본 세팅

apt 패키지 관리자 사용을 위한 업데이트 : sudo apt update
vim 설치 : sudo apt install rdate vim -y

데이터 센싱을 원활하게 하기 위한 시간 세팅

LG U+ 타임 서버에서 시간 값 가져오기 : sudo rdate -s time.bora.net
서울로 셋팅 : sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

MYSQL 설치 및 세팅

MYSQL 설치 : sudo apt install mysql-server -y

관리자 계정 생성

sudo mysql
use mysql;
create user '아이디'@'%' identified with mysql_native_password by '비밀번호';

%는 어느 IP 접속 가능
with mysql_native_password는 키 인증 방식이 아닌 password 인증 방식을 사용하겠다는 의미

스키마 생성 및 권한 부여

스키마(엑셀 파일), Table(Sheet)
스키마 생성 : create database [DB스키마이름];
모든 권한 부여 : grant all privileges on [DB스키마이름].* to '아이디'@'%';

테스트 및 추가 설정

quit으로 sql을 종료 후 mysql -u '아이디' -p을 통해 테스트하기
mysql을 ssh 뿐만 아니라 외부 접속도 가능케 하기 : sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf에서 bind-address를 0.0.0.0으로 설정하기!
재시작하여 설정 내용 적용하기 : sudo service mysql restart

MYSQL 접속

MYSQL Workbench 설치+을 통해 계정 생성하기!
제목, AWS에서 생성한 IPv4 주소, 생성한 관리자 계정을 입력하여 접속 테스트 후 접속하기!
2개의 테이블을 생성할 것입니다. 클라우드 Sever로 부터 원격 조정기를 통해 보내온 명령어를 읽는 명령어 Table 과 RC Car가 센서로 부터 읽은 데이터를 클라우드 Server에 보낼 sensing Table을 생성합니다.

스키마 더블클릭하여 스키마에 접근 후 다음 SQL문을 입력하여 테이블 생성하기!

CREATE TABLE `command` (
	`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`time` DATETIME NULL,
	`cmd_string` VARCHAR(50) NULL DEFAULT NULL,
	`arg_string` VARCHAR(50) NULL DEFAULT NULL,
	`is_finish` INT NULL
);

CREATE TABLE `sensing` (
	`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`time` DATETIME NULL,
	`num1` DOUBLE NULL DEFAULT NULL,
	`num2` DOUBLE NULL DEFAULT NULL,
	`num3` DOUBLE NULL DEFAULT NULL,
	`meta_string` VARCHAR(50) NULL DEFAULT NULL,
	`is_finish` INT NULL
);

원격조정기

원격조정기를 통해 제어 명령어를 클라우드 서버에 전송하면, RC카가 해당 명령어를 읽어 들여 명령어에 맞게 작동되게 설계하였습니다.

개발 PC로 Windows 환경인 파이참에서 PySide6로 원격조정기를 개발합니다. 개발 및 Test가 완료 후에는 소스코드를 Raspberry Pi 에서 가져간 뒤, PySide2로 변경하여 App을 실행합니다.

Pyside 6 설치 및 셋팅

프로젝트를 하나 생성합니다. 폴더 경로에 한글이 포함되어있다면, 에러가 발생합니다.

파이썬에서는 외부 Library를 패키지라고 부릅니다. 먼저 PySide 패키지를 설치해봅시다. 설정에서 프로젝트 > 인터프리터 > 빈곳 더블클릭하면 됩니다.
여기서 pyside6 를 선택하고 “설치” 를 누르면 패키지 설치가 진행됩니다.

테스트

from PySide6.QtWidgets import *

app = QApplication()
btn = QPushButton("Test Button")
btn.show()
app.exec()

GUI 에디터 셋팅

PySide를 사용하여 GUI 개발을 하는데, 매번 venv > lib > site-package > pyside > designer.exe 를 수행하기에는 번거롭습니다.

바로가기 제작

따라서, 바로가기를 만들어 편리하게 pyside를 수행합시다.

설정 > 도구 > 외부도구에 + 버튼을 누릅니다.

이름, 프로그램(경로: 생성된 프로젝트 명 > venv > Lib > site-packages > PySide6 > desinger.exe) > 고급옵션(도구 출력용 콘솔 열기 끄기) > 확인

설정 완료 후 좌측 탭 빈곳에서 마우스 오른쪽 버튼 후 외부 도구에서 실행시키기

DB 패키지 설치

MySQL 공식 Connection 방법을 이용하여 DB와 Pyside 연결하기!
설정에서 프로젝트 > 인터프리터 > 빈곳 더블클릭하면 됩니다.
여기서 mysql-connectormysql-connector-python를 선택하고 “설치” 를 누르면 패키지 설치가 진행됩니다.

테스트

from PySide6.QtWidgets import *
import mysql.connector

db = mysql.connector.connect(host='AWS IPv4 주소', user='관리자 계정 아이디', password='관리자 계정 비밀번호', database='생성한 스키마명')
cur = db.cursor() # query의 결과를 저장하는 공간을 나타내는 Database 명령어

#query
cur.execute("select * from command")

#print : 생성한 행 이름에 맞게 설정
for (id, time, cmd_string, arg_string, is_finish) in cur:
    print(id, time, cmd_string, arg_string, is_finish)

cur.close()
db.close()

UI 제작

아까 만들어둔 desginer 바로가기를 통해 designer을 실행시킵니다.
Main Window에서 PlainTextEditPush Button 위젯을 생성해줍니다.
PlainTextEdit의 객체명은 logText로 Push Button의 객체명은 startButton으로 설정해줍니다.
버튼 클릭시 start()라는 함수가 실행되도록 Signal & Slot을 연결해줍니다.

venv 폴더 밖 경로에 mainUI.ui 파일명으로 파일을 저장합니다.

바로가기 제작

ui 파일을 py로 convert 해줘야하는데, 이 또한 바로가기로 제작해봅니다!

설정 > 도구 > 외부도구에 + 버튼을 누릅니다.

이름, 프로그램(경로: 생성된 프로젝트 명 > venv > Scripts > pyside6-uic.exe),인수(FileDirFileDir\mainUI.ui -o FileDirFileDir\mainUI.py) , 고급옵션(도구 출력용 콘솔 열기 끄기) > 확인

설정 완료 후 좌측 탭 빈곳에서 마우스 오른쪽 버튼 후 외부 도구에서 실행시키기

UI 테스트 코드

from PySide6.QtWidgets import *
from mainUI import Ui_MainWindow

class MyApp(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.init()

    def init(self):
        print("INIT")

    def start(self):
        print("START")

app = QApplication()
win = MyApp()
win.show()
app.exec()

Pyside6 - DB 연결 코드

from PySide6.QtWidgets import *
from mainUI import Ui_MainWindow
import mysql.connector

class MyApp(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.init()

    def init(self):
        self.db = mysql.connector.connect(host='AWS IPv4 주소', user='관리자 계정 아이디', password='관리자 계정 비밀번호', database='생성한 스키마명')
        self.cur = self.db.cursor()


    def start(self):
        self.cur.execute("select * from command")
        for (id, time, cmd_string, arg_string, is_finish) in self.cur:
            print(id, time, cmd_string, arg_string, is_finish)

    def closeEvent(self, event):
        self.cur.close()
        self.db.close()

app = QApplication()
win = MyApp()
win.show()
app.exec()

QTimer을 이용하여 반복적으로 Query하기

from PySide6.QtWidgets import *
from PySide6.QtCore import *
from mainUI import Ui_MainWindow
import mysql.connector

class MyApp(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.init()

    def init(self):
        self.db = mysql.connector.connect(host='AWS IPv4 주소', user='관리자 계정 아이디', password='관리자 계정 비밀번호', database='생성한 스키마명')
        self.cur = self.db.cursor()

        #timer setting
        self.timer = QTimer()
        self.timer.setInterval(500) #500ms
        self.timer.timeout.connect(self.pollingQuery)

    def start(self):
        self.timer.start()

    def pollingQuery(self):
        self.cur.execute("select * from command")
        self.ui.logText.clear()
        for (id, time, cmd_string, arg_string, is_finish) in self.cur:
            str = "%d | %s | %6s | %6s | %4d" % (id, time.strftime("%Y%m%d %H:%M:%S"), cmd_string, arg_string, is_finish)
            self.ui.logText.appendPlainText(str)

    def closeEvent(self, event):
        self.cur.close()
        self.db.close()

app = QApplication()
win = MyApp()
win.show()
app.exec()

버튼 추가

logText의 font를 Consolas로 수정하기
Go(객체명: goButton, slot: go()), Back(객체명: backButton, slot: back()), Mid(객체명: midButton, slot: mid()), Left(객체명: leftButton, slot: left()), Right(객체명: rightButton, slot: right()), STOP(객체명: stopButton, slot: stop()) 추가하기

테스트

from PySide6.QtWidgets import *
from PySide6.QtCore import *
from mainUI import Ui_MainWindow
import mysql.connector

class MyApp(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.init()

    def init(self):
        self.db = mysql.connector.connect(host='AWS IPv4 주소', user='관리자 계정 아이디', password='관리자 계정 비밀번호', database='생성한 스키마명')
        self.cur = self.db.cursor()

        #timer setting
        self.timer = QTimer()
        self.timer.setInterval(500) #500ms
        self.timer.timeout.connect(self.pollingQuery)

    def start(self):
        self.timer.start()

    def pollingQuery(self):
        self.cur.execute("select * from command")
        self.ui.logText.clear()
        for (id, time, cmd_string, arg_string, is_finish) in self.cur:
            str = "%d | %s | %6s | %6s | %4d" % (id, time.strftime("%Y%m%d %H:%M:%S"), cmd_string, arg_string, is_finish)
            self.ui.logText.appendPlainText(str)

    def closeEvent(self, event):
        self.cur.close()
        self.db.close()
        
    def insertCommand(self, cmd_string, arg_string):
        time = QDateTime().currentDateTime().toPython()
        is_finish = 0

        query = "insert into command(time, cmd_string, arg_string, is_finish) values (%s, %s, %s, %s)"
        value = (time, cmd_string, arg_string, is_finish)

        self.cur.execute(query, value)
        self.db.commit()

    def go(self):
        self.insertCommand("go", "5")
        
    def stop(self):
        self.insertCommand("stop", "0")

    def back(self):
        self.insertCommand("back", "0")

    def left(self):
        self.insertCommand("left", "0")

    def mid(self):
        self.insertCommand("mid", "0")

    def right(self):
        self.insertCommand("right", "0")

app = QApplication()
win = MyApp()
win.show()
app.exec()

Sensing Table 추가하기

logText를 객체명: sensingText, Font: Consolas로 추가합니다.

테스트

from PySide6.QtWidgets import *
from PySide6.QtCore import *
from mainUI import Ui_MainWindow
import mysql.connector

class MyApp(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.init()

    def init(self):
        self.db = mysql.connector.connect(host='AWS IPv4 주소', user='관리자 계정 아이디', password='관리자 계정 비밀번호', database='생성한 스키마명')
        self.cur = self.db.cursor()

        #timer setting
        self.timer = QTimer()
        self.timer.setInterval(500) #500ms
        self.timer.timeout.connect(self.pollingQuery)

    def start(self):
        self.timer.start()

    def pollingQuery(self):
        self.cur.execute("select * from command order by time desc limit 15")
        self.ui.logText.clear()
        for (id, time, cmd_string, arg_string, is_finish) in self.cur:
            str = "%d | %s | %6s | %6s | %4d" % (id, time.strftime("%Y%m%d %H:%M:%S"), cmd_string, arg_string, is_finish)
            self.ui.logText.appendPlainText(str)

        self.cur.execute("select * from sensing order by time desc limit 15")
        self.ui.sensingText.clear()
        for (id, time, num1, num2, num3, meta_string, is_finish) in self.cur:
            str = "%d | %s | %6s | %6s | %6s | %10s | %4d" % (id, time.strftime("%Y%m%d %H:%M:%S"), num1, num2, num3, meta_string, is_finish)
            self.ui.sensingText.appendPlainText(str)

    def closeEvent(self, event):
        self.cur.close()
        self.db.close()

    def insertCommand(self, cmd_string, arg_string):
        time = QDateTime().currentDateTime().toPython()
        is_finish = 0

        query = "insert into command(time, cmd_string, arg_string, is_finish) values (%s, %s, %s, %s)"
        value = (time, cmd_string, arg_string, is_finish)

        self.cur.execute(query, value)
        self.db.commit()

    def go(self):
        self.insertCommand("go", "0")

    def stop(self):
        self.insertCommand("stop", "0")

    def back(self):
        self.insertCommand("back", "0")

    def left(self):
        self.insertCommand("left", "0")

    def mid(self):
        self.insertCommand("mid", "0")

    def right(self):
        self.insertCommand("right", "0")

app = QApplication()
win = MyApp()
win.show()
app.exec()
profile
여러 방향으로 접근하는 개발자

0개의 댓글