본문으로 바로가기
반응형

Flask

플라스크는 파이썬 언어를 통해 웹개발을 할 수 있게 해주는 웹개발 프레임워크 중 하나이다.

웹개발 프레임워크는 개발자가 웹을 더 쉽게 개발할 수 있도록 여러 라이브러리를 제공하는 툴이라고 볼 수 있다.

라즈베리파이는 아주 가벼운 서버형태를 제공하는데, 웹서버를 만들어보자.

 

 

VNC에 라즈베리를 접속한 후에 해당 코드를 작성하고 실행해보자.

# 파일이름 : flaskTest.py
from flask import Flask     # from: Flask 폴더에서 flask모듈을 import하겠다는 뜻

app = Flask(__name__)       # Flask라는 이름의 객체 생성

@app.route('/')             # 클라이언트가 ui창에다가 /로 접속하면 hello함수 호출

def hello():                # /로 실행하면 호출되는 뷰함수
   return "Hello Flask!"    # 뷰함수는 반드시 retrun이 있어야한다.

if __name__ == "__main__":  # 직접 main을 실행시키기위한 조건
   app.run(host="0.0.0.0", port = "8080")

코드 실행 후 터미널화면

이때 맨밑에 있는 if __name__ == "__main__":   은 파이썬에서 메인함수를 선언하는 것으로 보면된다.

 

 

코드를 실행했을때 위의 이미지처럼 코드들이 떴다면 서버구축이 완료된 상태이다.

인터넷창에서 본인의 라즈베리파이 주소:5000  을 쳐서 들어가보면 Hello Flask!가 출력되있는 것을 확인할 수 있다.

 

 

PuTTY에 실행해서 새 인터넷창에도 "Hello Flask!"를 출력해보자.

VNC뿐만아니라 컴퓨터에서도 호출할 수 있다

 

 

 

메인 홈페이지에서 name, age, job, about 페이지를 또 만들어서 호출해보자.

# 파일이름 : flask01.py
from flask import Flask     

app = Flask(__name__)       

@app.route('/')             
def hello():                
   return "Hello Flask!"    
   
@app.route('/name')
def name():
   return "<h1> My name is youname </h1>" # html 문법도 적용할 수 있다
   
@app.route('/age')
def name():
   return "<h2> My age is 27 </h2>"
   
@app.route('/job')
def name():
   return "<h3> My job is developer </h3>"
   
@app.route('/about')
def about():
   return "<h1> My name is SeoDongWoo </h1> <h2> My age is 27 years old </h2> <h3> my job is developer </h3>"

if __name__ == "__main__": 
   app.run(host="0.0.0.0", port = "8080")

코드를 실행했을때의 PuTTY 화면

 

웹에 접속했을때 화면

 

이제 웹개발 프레임워크를 통해 웹을 만들어봤으니 LED를 이용해서 하드웨어를 설계하는 단계로 넘어가보자.

 

 

웹 사이트에 접속했을때 LED를 키고, 끄는 코드를 작성해보자.

from flask import Flask
import RPi.GPIO as GPIO

app = Flask(__name__)

ledPin = 21

@app.route('/')
def flask():
   GPIO.setmode(GPIO.BCM)        # setmode를 BCM으로 설정
   GPIO.setup(ledPin, GPIO.OUT)  # 21번핀을 설정
   GPIO.output(ledPin, 0)        # 처음에는 일단 꺼둔 상태
   return "Hello Flask"

@app.route('/led/on')
def ledOn():
   GPIO.output(ledPin, 1)        # LED 킴
   return "<h1> LED ON </h1> "

@app.route('/led/off')
def LedOff():
   GPIO.output(ledPin, 0)        # LED 끔
   return "<h1> LED OFF </h1>"

@app.route('/led/clean')
def clean():
   GPIO.cleanup()                 # 핀을 클린시키는 코드
   return "<h1> GPIO Clean </h1>"

if __name__ == "__main__":
   app.run(host = "0.0.0.0", port = "8080")

사이트 들어갈때마다 뜨는 PuTTY창 화면
웹 결과화면

 

LED Off(좌)                                                                                     LED On(우)

 

GPIO.cleanup() 을 해주면 라즈베리파이의 모든 핀이 초기화된다.

따라서 핀이 초기화된 상태에서 LED on, off를하려면 사이트에 에러가뜬다.

이는 핀이 초기화되서 21번핀에대한 정보가 없는데 output으로 불을 키라고했기때문에 런타임에러가 뜨는 것이다.

 

다시 LED를 키려면 메인 홈페이지에 접속했을때 ( @app.route('/')가 호출됬을때)

다시 setmode, setup을 해주어야 핀을 설정해줘야 cleanup() 이후에도 LED 제어를 할 수 있다.

 

위의 코드는 메인페이지/led/on, 메인페이지/led/off 처럼 꼭 on, off가 와야 해당 페이지에 접속할 수 있는데, 이것을 정적 라우팅이라고한다.

 

호출된 함수에 매개변수를 넣어서 해당되는 문자열이오면(조건문사용) LED를 키고, 끌 수 있도록하는 동적라우팅 코드를 작성해보자.

from flask import Flask
import RPi.GPIO as GPIO

app = Flask(__name__)

ledPin = 21
GPIO.setmode(GPIO.BCM)
GPIO.setup(ledPin, GPIO.OUT)

@app.route('/')
def ledFlask():
   return "<h1> LED Control WepPage </h1>"

@app.route('/led/<state>')  # /이 매개변수로 와야함, 동적라우팅 함수 작성
def led(state):             # state를 매개변수로 받고 문자열에따른 조건문 작성
   if(state == 'on'):
      GPIO.output(ledPin, 1)  # LED 키고
   else:
      GPIO.output(ledPin, 0)  # LED 끄고
   return ("<h1> LED %s </h1>" %state)

@app.route('/led/clean')
def clean():
   GPIO.output(ledPin, GPIO.LOW)
   GPIO.cleanup()
   return "<h1> GPIO Clean!! </h1>"

if __name__ == "__main__":
   app.run(host = "0.0.0.0", port = "8080")

 

LED 끄자. 페이지를 봤을때, 조건문에서는 state 입력이 'on'일때를 제외하고 모든 문자열을 else문을통해 LED를 끄도록 설정했기때문에, on말고 어떤 문자열이와도 LED를 끄고 입력한 문자열을 return을 통해 반환하도록 함수를 작성했다.

(참고로 스마트폰 웹에서도 작동되는 것을 확인할 수도 있다)

 

이렇게 정해진 on, off가 아니라 다른 문자열로도 접속할 수 있도록 설계하는것이 동적 라우팅이라고 볼 수 있다.

 

 

 

 

이번에는 Html 파일로 웹페이지를 흉내 내보자. (웹의 버튼이나 텍스트박스같은 컴포넌트로 LED를 제어해보자)

 

 

현재 디렉터리에 webLed.py 생성,

현재 디렉터리에 templates 디렉터리를 만들고 templates 디렉터리에 html 파일 생성

 

쨋든 webLed.py 과 index.html 이 같은 디렉터리에 있으면 안되고, (templates 디렉터리도 필수!)

webLed.py 파일이 index.html 의 상위 디렉터리에 존재해야한다.

 

코드를 작성하기 전에 웹에서 GET/POST 방식을 알고 있어야하는데,

GET 방식은 주소창으로 정보나 데이터를 보내고

POST 방식은 주소가아닌 사이트 자체의 컴포넌트등에서 정보나 데이터를 보내는 방식(예를들면 버튼이 있다)

 

웹의 버튼을 이용해서 LED를 제어하는 코드를 작성해보자.(POST 전달 채용)

 

index.html 파일

티스토리 코드블럭 시스템이 개떡같으므로 이미지로 대체

 

# 파일명 : webLed.py

from flask import Flask, request, render_template # 3개를 import
import RPi.GPIO as GPIO

app = Flask(__name__)

ledPin = 21
GPIO.setmode(GPIO.BCM)
GPIO.setup(ledPin, GPIO.OUT)

@app.route('/')
def home():
   return render_template("index.html")


@app.route('/data', methods = ['POST'])
def data():
   data = request.form['led'] # led라는 이름을통해 form에 집어넣은걸
                              # data에 저장

   if(data == 'on'):
      GPIO.output(ledPin, 1)  # LED 켜줌
      return home()
   elif(data == 'off'):
      GPIO.output(ledPin, 0)  # LED 끔
      return home()
   elif(data == 'clean'):     # GPIO를 cleanup으로 초기화
      GPIO.cleanup()
      return home()
   elif(data == 'Restart'):   # clean 이후에 다시 LED를 제어하고싶을때 GPIO를 다시 세팅
      try:
         GPIO.setmode(GPIO.BCM)
         GPIO.setup(ledPin, GPIO.OUT)
         return home()
      except:
         print("이미 핀이 설정되있습니다")
         return home()

if __name__ == '__main__':
   app.run(host = '0.0.0.0', port = '8080')

POST 방식의 정보정달로인해 버튼을 클릭하면 버튼의 value가 'data' 라는 값으로 파이썬 코드에 전달된다.
각 버튼을 눌러도 return home() 때문에 계속 이 페이지에 남아있는 것처럼 구현

 

 

위의 코드들을 대충 훑어보면,

메인 홈페이지에 접속하면 index.html이 호출된다.

메인 홈피에서 html 코드에의해 버튼이 4개가 만들어지는데, 이때 버튼을 클릭하면 value값이 파이썬의 data함수의 data에 저장된다.

이때 data의 값에따라 LED on, off, clean, restart 의 조건문을 실행하게 된다.

각 조건문마다 return home()으로 처리를 했는데, 버튼을 클릭했을때 다른 페이지로 넘어가기 전에 다시 home()을 호출해서 메인홈페이지에 계속 머물러서 버튼제어를 하는것처럼 코드를 구현했다.

 

 

반응형