이름, 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 설치 : 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 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을 실행합니다.
프로젝트를 하나 생성합니다. 폴더 경로에 한글
이 포함되어있다면, 에러가 발생합니다.
파이썬에서는 외부 Library를 패키지
라고 부릅니다. 먼저 PySide 패키지를 설치해봅시다. 설정에서 프로젝트 > 인터프리터 > 빈곳 더블클릭
하면 됩니다.
여기서 pyside6
를 선택하고 “설치” 를 누르면 패키지 설치가 진행됩니다.
테스트
from PySide6.QtWidgets import *
app = QApplication()
btn = QPushButton("Test Button")
btn.show()
app.exec()
PySide를 사용하여 GUI 개발을 하는데, 매번 venv > lib > site-package > pyside > designer.exe 를 수행하기에는 번거롭습니다.
따라서, 바로가기
를 만들어 편리하게 pyside를 수행합시다.
설정 > 도구 > 외부도구에 + 버튼
을 누릅니다.
이름, 프로그램(경로: 생성된 프로젝트 명 > venv > Lib > site-packages > PySide6 > desinger.exe) > 고급옵션(도구 출력용 콘솔 열기
끄기
) > 확인
설정 완료 후 좌측 탭 빈곳에서 마우스 오른쪽 버튼 후 외부 도구
에서 실행시키기
MySQL 공식 Connection 방법을 이용하여 DB와 Pyside 연결하기!
설정에서 프로젝트 > 인터프리터 > 빈곳 더블클릭
하면 됩니다.
여기서 mysql-connector
와 mysql-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()
아까 만들어둔 desginer 바로가기를 통해 designer을 실행시킵니다.
Main Window
에서 PlainTextEdit
과 Push Button
위젯을 생성해줍니다.
PlainTextEdit의 객체명은 logText
로 Push Button의 객체명은 startButton
으로 설정해줍니다.
버튼 클릭시 start()라는 함수가 실행되도록 Signal & Slot을 연결해줍니다.
venv 폴더 밖 경로에 mainUI.ui
파일명으로 파일을 저장합니다.
ui 파일을 py로 convert 해줘야하는데, 이 또한 바로가기로 제작해봅니다!
설정 > 도구 > 외부도구에 + 버튼
을 누릅니다.
이름, 프로그램(경로: 생성된 프로젝트 명 > venv > Scripts > pyside6-uic.exe),인수(\mainUI.ui -o \mainUI.py) , 고급옵션(도구 출력용 콘솔 열기
끄기
) > 확인
설정 완료 후 좌측 탭 빈곳에서 마우스 오른쪽 버튼 후 외부 도구
에서 실행시키기
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()
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()
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()
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()