정보보안(34회차) 노트


micro:bit를 이용한 초등돌봄출석관리시스템 개발
step1
학생 micro:bit

radio 통신

교사용 micro:bit

USB

PC 출석 프로그램 (Python)

출석파일 저장 (Excel)

[학생용]
from microbit import *
import radio
radio.on()
radio.config(group=1)
student_id = "S01"
while True:
if button_a.was_pressed():
radio.send(student_id)
display.show(Image.HAPPY)
sleep(1000)
display.clear()

[교사용]
from microbit import *
import radio
radio.on()
radio.config(group=1)
while True:
msg = radio.receive()
if msg:
print(msg)
display.show(Image.YES)
sleep(500)
display.clear()

[교사용관리프로그램]
pip install pyserial
import serial
import datetime
ser = serial.Serial('COM3',115200)
while True:
data = ser.readline().decode().strip()
if data:
time = datetime.datetime.now()
with open("attendance.csv","a") as f:
f.write(f"{data},{time}\n")
print("출석:", data)

step2
기능개선작업
LED 이름 표시 출석판
출석하면 멜로디 재생
지각하면 슬픈 얼굴 표시
*코드를 해석해보세요*
사용된 문법은 무엇인가요? 청소년IT경시대회 코드와의 차이점은 무엇인가요?
pip install pyserial pandas openpyxl
import serial
import datetime
import pandas as pd
# COM 포트 수정
ser = serial.Serial('COM3',115200)
# 학생 목록
students = {
"S01":"조영우",
"S02":"이성원",
"S03":"홍길동",
"S04":"홍길순"
}
attendance = {}
print("출석 시스템 시작")
while True:
data = ser.readline().decode().strip()
if data:
sid, status = data.split(",")
name = students.get(sid,"Unknown")
now = datetime.datetime.now()
time = now.strftime("%H:%M:%S")
if sid not in attendance:
attendance[sid] = {}
if status == "IN":
if "in" not in attendance[sid]:
attendance[sid]["in"] = time
if now.hour >= 14:
print(name,"지각")
else:
print(name,"출석")
if status == "OUT":
attendance[sid]["out"] = time
print(name,"하교")
save_list = []
for sid in attendance:
save_list.append([
sid,
students.get(sid),
attendance[sid].get("in",""),
attendance[sid].get("out","")
])
df = pd.DataFrame(save_list,columns=["학번","이름","등원","하교"])
df.to_excel("attendance.xlsx",index=False)


step3
기능개선작업
LED 이름 표시 출석판
출석하면 멜로디 재생
import music music.play(music.POWER_UP) 지각하면 슬픈 얼굴 표시
출석 카운터하기
교실 출석판 만들기
1️⃣ micro:bit 자동 학생ID 설정 프로그램
2️⃣ 출석 GUI 프로그램 (버튼형)
3️⃣ 웹 출석 시스템
4️⃣ QR코드 출석 시스템
5️⃣ RFID 카드 출석 시스템
학생 micro:bit
↓ (radio)
교사용 micro:bit
↓ USB
라즈베리파이

Python Serial 수신

Flask 웹 서버

웹 브라우저 (실시간 출석판)
라즈베리파이 준비
가상환경구축및 서버 구축 방법 바로가기
sudo apt update
pip install flask pyserial pandas openpyxl
플라스크 코드 수정하기
from flask import Flask, render_template, jsonify
import serial
import datetime
import threading
import json
import pandas as pd
app = Flask(__name__)
ser = serial.Serial('/dev/ttyACM0',115200)
with open("students.json","r",encoding="utf-8") as f:
students = json.load(f)
attendance = {}
def read_serial():
while True:
data = ser.readline().decode().strip()
if data:
sid,status = data.split(",")
name = students.get(sid,"Unknown")
now = datetime.datetime.now()
time = now.strftime("%H:%M:%S")
if sid not in attendance:
attendance[sid] = {
"name":name,
"in":"",
"out":"",
"status":""
}
if status == "IN":
attendance[sid]["in"] = time
attendance[sid]["status"] = "출석"
if status == "OUT":
attendance[sid]["out"] = time
attendance[sid]["status"] = "하교"
save_excel()
def save_excel():
data = []
for sid in attendance:
a = attendance[sid]
data.append([
sid,
a["name"],
a["in"],
a["out"],
a["status"]
])
df = pd.DataFrame(data,columns=["학번","이름","등원","하교","상태"])
df.to_excel("attendance.xlsx",index=False)
@app.route("/")
def index():
return render_template("index.html")
@app.route("/data")
def data():
return jsonify(attendance)
thread = threading.Thread(target=read_serial)
thread.daemon = True
thread.start()
if __name__ == "__main__":
app.run(host="0.0.0.0",port=5000)

추가기능
지각 표시
출석 인원 표시
스마트폰 확인
학부모용 페이지

step4
다중과목지원으로 기능 추가하기
학생 micro:bit

radio 전송

교사용 micro:bit
↓ USB
라즈베리파이

Flask 서버

과목별 출석 데이터 저장
↓ 웹 대시보드 (과목 선택)
from microbit import *
import radio
radio.on()
radio.config(group=10)
student_id = "S01"
subjects = ["MATH","SCI","ENG"]
subject_index = 0
display.scroll(subjects[subject_index])
while True:
if button_a.is_pressed() and button_b.is_pressed():
subject_index = (subject_index + 1) % len(subjects)
display.scroll(subjects[subject_index])
sleep(500)
if button_a.was_pressed():
msg = f"{student_id},{subjects[subject_index]},IN"
radio.send(msg)
display.show(Image.HAPPY)
sleep(1000)
display.clear()
if button_b.was_pressed():
msg = f"{student_id},{subjects[subject_index]},OUT"
radio.send(msg)
display.show(Image.SAD)
sleep(1000)
display.clear()

attendance = {}
def read_serial():
while True:
data = ser.readline().decode().strip()
if data:
sid,subject,status = data.split(",")
now = datetime.datetime.now()
time = now.strftime("%H:%M:%S")
if subject not in attendance:
attendance[subject] = {}
if sid not in attendance[subject]:
attendance[subject][sid] = {
"name":students.get(sid),
"in":"",
"out":"",
"status":""
}
if status == "IN":
attendance[subject][sid]["in"] = time
attendance[subject][sid]["status"] = "출석"
if status == "OUT":
attendance[subject][sid]["out"] = time
attendance[subject][sid]["status"] = "하교"

step5
┌──────────────────────┐
│ 학생 micro:bit │
│ (학생ID + 과목 + 상태)│
└──────────┬───────────┘
│ radio

┌──────────────────────┐
│ 교사용 micro:bit │
│ (radio → USB Serial) │
└──────────┬───────────┘
│ USB

┌─────────────────────────────┐
│ Raspberry Pi 출석 서버 │
│ │
│ Serial 수신 서비스 │
│ ↓ │
│ 출석 처리 로직 │
│ ↓ │
SQLite DB 저장
│ ↓ │
│ Flask Web API │
└──────────┬──────────────────┘


┌───────────────────────────┐
│ Web Dashboard │
│ │
│ 출석 현황 │
│ 과목별 조회 │
│ 지각 체크 │
출석 통계
└──────────┬────────────────┘


┌─────────────────────────────┐
│ 관리 기능 │
│ │
│ Excel 다운로드 │
│ 학생 관리 │
│ 시간표 관리 │
출석 기록 조회
└─────────────────────────────┘