IP카메라 웹기반 설정
실습 목표:
Python-Flask 기반의 웹 서버를 이용하여 IP카메라 설정을 변경하고, 캡쳐된 사진을 웹 브라우져로 가져와서 보여준다.필요 기술:
웹: HTML5, Javascript, jQuery, Ajax, FlaskOS: 시그널
참고:
쉘에서 시그널 보내기$ kill -s SIGUSR1 PID
파이선에서 시그널 보내기
os.kill(PID, signal.SIGUSR1)
여기에서 PID는 프로세스ID
예제 코드
https://gist.github.com/jyheo/2bfba7a45cafff1c811a5c11c53160d4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> | |
<script> | |
$(document).ready(function(){ | |
$("#capture_button").click(function(){ | |
var ts = new Date().getTime(); | |
$("#div1").html("<img src='/capture?timestamp=" + ts + "'/>"); | |
}); | |
$("#config_button").click(function(event) { | |
var formData = $("#config_form").serialize(); | |
$.get("/config?" + formData, function(data, status) { | |
alert(data + "\nStatus: " + status); | |
}); | |
event.preventDefault(); | |
}); | |
}); | |
</script> | |
</head> | |
<body> | |
<h2> Configuration </h2> | |
<form id="config_form"> | |
Annotate Text:<br/> | |
<input type="text" name="annotate" value="CAM1"> | |
<br/> | |
<br/> | |
Resolution:<br/> | |
<input type="radio" name="resolution" value="1920x1080" checked> 1920x1080<br> | |
<input type="radio" name="resolution" value="1280x720"> 1280x720<br> | |
<input type="radio" name="resolution" value="640x480"> 640x480<br> | |
<!-- | |
TODO: Brightness, Contrast, image_effect 와 같은 다른 설정도 추가해볼 것 | |
--> | |
<button id="config_button">Save</button> | |
</form> | |
<hr> | |
<button id="capture_button">Capture</button> | |
<div id="div1"><h2>Capture Image</h2></div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from flask import Flask, send_file, render_template, request | |
app = Flask(__name__) | |
@app.route('/') | |
def index(): | |
return render_template('config.html') # config.html은 templates/config.html 에 위치해야 함. | |
@app.route('/config') | |
def config(): | |
resolution = request.args.get('resolution', '') | |
annotate = request.args.get('annotate', '') | |
print resolution, annotate | |
# TODO: resolution, annotate 설정을 특정 파일에 저장한다. 저장 방법은 xml이나 pickle 등을 사용 | |
# 캡쳐 프로그램이 설정을 다시 읽도록 SIGUSR1 시그널을 보낸다. | |
return 'OK' | |
@app.route('/capture') | |
def capture(): | |
return send_file('foo.jpg') # 캡쳐 프로그램이 캡쳐한 파일 전송 | |
if __name__ == '__main__': | |
app.run('0.0.0.0') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import signal, os, time | |
from threading import Lock | |
lck = Lock() | |
resolution = "1920x1080" # 설정 변수 예 | |
def signal_handler(signum, frame): | |
print 'Signal handler called with signal', signum | |
lck.acquire() | |
# TODO: ipcam_config.py 가 새로 저장한 설정을 읽어서 설정 변수를 변경한다. | |
lck.release() | |
signal.signal(signal.SIGUSR1, signal_handler) | |
# TODO: 이 프로세스의 PID를 특정 파일에 저장하여, 시그널을 보낼 프로그램(ipcam_config.py)이 PID를 알 수 있도록 한다. | |
print 'PID:', os.getpid() | |
while True: | |
lck.acquire() | |
# TODO: 변경된 설정을 반영한다. | |
lck.release() | |
# TODO: 적당한 간격으로 캡쳐 한다. | |
time.sleep(10) |