코딩 이야기
Flask 웹페이지 본문
Flask, HTML, CSS, Javascript를 이용한 웹페이지 만들기
기본 폴더 구성은 아래와 같습니다.
webapps
-ch06
-home
-static
-templates
폴더 구조를 보면 home 이라는 폴더가 최상위 root 폴더가 됩니다. 그리고 그 아래에 static 폴더가 있는데 flaks에서는 해당 폴더를 리소스(자원) 폴더로 사용합니다. css, image, media 등의 파일을 해당 폴더에 저장합니다. templates 폴더는 html 파일 폴더로 사용합니다. templates 폴더를 사용할 때 유의사항은 flask는 기본적으로 view랜더리을 할 때 html 파일을 호출하는데 html 파일은 무조건 templates 폴더에 있는 html 파일을 호출하게끔 설정이 되어 있습니다. 그렇기 떄문에 temp라는 폴더를 만들게 되면 폴더명이 다르기 때문에 렌더링이 되지 않습니다.
파이썬
from flask import Flask, request
from flask import render_template
import RPi.GPIO as GPIO
app = Flask(__name__)
GPIO.setmode(GPIO.BOARD) #BOARD는 커넥터 pin번호 사용
GPIO.setup(8, GPIO.OUT, initial=GPIO.LOW)
@app.route("/")
def home():
return render_template("index.html")
@app.route("/led/on")
def led_on():
try:
GPIO.output(8, GPIO.HIGH)
return "ok"
except expression as identifier:
return "fail"
@app.route("/led/off")
def led_off():
try:
GPIO.output(8, GPIO.LOW)
return "ok"
except expression as identifier:
return "fail"
if __name__ == "__main__":
app.run(host="0.0.0.0")
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HOME NETWORK</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<div class="container">
<div class="header">
<h2>HOME IoT</h2>
</div>
<div class="main">
<div>
<button onclick="led_on()">LED ON</button>
</div>
<div>
<button onclick="led_off()">LED OFF</button>
</div>
</div>
<div id="result">
</div>
</div>
<script>
function led_on(){
fetch("/led/on")
.then(response=> { console.log(response); return response.text()})
.then(data=> {
console.log(data);
let result = document.querySelector("#result");
if(data=="ok"){
result.innerHTML = "<h1>LED is runinng</h1>";
}else{
result.innerHTML = "<h1>error</h1>";
}
});
}
function led_off(){
fetch("/led/off")
.then(response=> response.text())
.then(data=> {
console.log(data);
let result = document.querySelector("#result");
if(data=="ok"){
result.innerHTML = "<h1>LED is stopping</h1>";
}else{
result.innerHTML = "<h1>error</h1>";
}
});
}
</script>
</body>
</html>
css
body {
background-color: antiquewhite;
}
.container {
width: 700px;
margin: 0 auto;
text-align: center;
}
.main {
display: flex;
}
.main div {
flex:1;
}
.main div button {
background-color: rgb(192, 114, 114);
width:150px;
height:80px;
border-radius: 10px;
}
python home.py
실행 합니다.
1.라즈베리 파이에서 브라우저를 열어서 확인할 경우
http://localhost:5000/
2.다른 PC에서 브라우저를 열어서 확인할 경우
http://192.168.0.80:5000
아이피 주소를 확인하고 싶은 경우
$ ifconfig
오류를 발생시켜 보겠습니다. index.py 파일을 다음과 같이 수정합니다.
from flask import Flask, request
from flask import render_template
import RPi.GPIO as GPIO
app = Flask(__name__)
GPIO.setmode(GPIO.BOARD) #BOARD는 커넥터 pin번호 사용
GPIO.setup(8, GPIO.OUT, initial=GPIO.LOW)
@app.route("/")
def home():
return render_template("index.html")
@app.route("/led/on")
def led_on();
try:
GPIO.output(9, GPIO.HIGH)
return "ok"
except expression as identifier:
return "fall"
@app.route("/led/off")
def led_off():
try:
GPIO.output(8, GPIO.LOW)
return "ok"
except expression as identifier:
return "fail"
if __name__ == "__main__":
app.run(host="0.0.0.0")
output GPIO핀 번호를 9번으로 변경하였습니다. 이렇게 되면 LED를 ON하려는 순간 GPIO 9번에 연결된 LED를 찾지 못하게 때문에 try부분에서 오류가 발생하고 except 부분으로 넘어가게 됩니다. 예외처리를 사용하면 예상하지 못한 서버오류로 서버가 멈추는 일이 발생하지 않도록 방지할 수 있습니다.
fetch() 함수 이해하기
index.html 코드에서 fetch라는 문법이 나오게 됩니다. 자바스크립트 문법입니다. ajax를 이용한 비동기 통신을 할 때 사용되는 라이브러리 입니다. fetch를 통해서 index.py led_on() 메서드를 호출하게 되고 그 결과를 response를 통해서 받습니다. len_on 메서드 호출 시에 실제 led가 on 이 되게 됩니다. 그리고 정상적으로 on 이되면 ok를 return 하게 됩니다. return 된 값을 fetch().then(reponse) 이 부분에서 then()이 받게 됩니다. then() 은 fetch가 완료된 뒤에 호출이 됩니다.
fetch는 요청 시에는 pending(대기)되고 있다가 요청이 완료되면 then(response)로 요청에 대한 결과를 return해주게 됩니다. 이를 통해 콜백 지옥을 벗어날 수 있습니다. promuse 기술이 들어가 있기 때문입니다. return 된 결과는 "ok" 메시지뿐만 아니라 수많은 정보를 가지고 있습니다. 이런 정보를 자바스크립트 오브 젝트로 만들어서 요청한 쪽으로 return해주게 되는 것입니다.
"ok" 메시지를 받으려면 then()이 한 번 더 필요합니다.
첫 번째 then()에서는 위 그림과 같이 전체 응답 오브젝트를 받습니다. 두 번째 then()은 그 많은 데이터중 "ok라는 메시지만 필터링 해줍니다. 서버 쪽에서 return 되는 결과가 String(문자열)이면 text()함수를 이용하고, JSON이면 json()함수를 이용하여 받으면 됩니다.
화살표 함수 이해하기
다음은 fech 함수의 then() 부분입니다.
then(
fucntion(response){
return response:
}
);
다음은 화살표 함수를 적용한 코드입니다. 위의 코드와 동일합니다.
then(
response => response;
);
중괄호를 넣을 경우에는 return문을 꼭 적어줘야 합니다. 대괄호를 넣지 않으면 return 문이 생략되어 있는 것과 같은 효과를 줍니다.
then(
response => { response };
);
매개 변수가 두개 이상이라면 기존 코드는 다음과 같이 진행합니다.
then(
function(response1, response2){
return response1;
}
);
화살표 함수에서는 다음과 같이 괄호를 사용합니다.
then(
(response1, response2) => [ return response1 };
);
then()안에 있는 함수는 이름이 필요없는 익명함수입니다.
then(
fucntion(response){
return response;
}
);
이름이 필요 없는 이유는 fextch()를 하고 어떤 결과를 받기까지 pending 하는데 pending 이 끝나면 자동으로 then()메서드가 실행이 되기 때문에 함수에 이름이 굳이 필요가 없습니다. 이름이 없어도 then()안에 함수는 자동으로 실행이 될 것이기 때문입니다.
'라즈베리파이' 카테고리의 다른 글
_cron과 daemon 개념잡기 (0) | 2023.03.08 |
---|---|
_IP ,Port, Process 개념잡기 (0) | 2023.03.08 |
Flask를 활용하여 센서 제어하기 (0) | 2023.03.07 |
라즈베리파이 GPIO 제어 및 테스트 (0) | 2023.03.07 |
라즈베리파이 GPIO 제어 및 테스트 (0) | 2023.03.07 |