memo6759 님의 블로그
2025-10-17 [라즈베리파이 mqtt ,쓰레드(상속,이너클래스)] 본문
익명 이너클래스
익명 이너 클래스란?
이름이 없는 클래스(anonymous class)
일회성으로 객체를 만들어야 할 때,
굳이 클래스를 따로 정의하지 않고 바로 ‘정의 + 생성’을 동시에 하는 방식
일회성작업
한 번만 쓸 클래스 만들기 귀찮을 때
일반 클래스 vs 익명 이너 클래스 비교
구분일반 클래스 익명 이너 클래스
| 정의 | 이름을 가진다 | 이름이 없다 |
| 재사용 | 가능 | 불가능 (일회성) |
| 파일 생성 | 별도 .java 필요 | 내부 코드에서 바로 작성 |
| 문법 | class 클래스명 {} | new 클래스() {} or new 인터페이스() {} |
파이썬 mqtt

라즈베리파이 GPIO LED 제어 실습 (Python)
1. 실습 목표
라즈베리파이의 GPIO 핀을 이용해 LED를 켜고 끄는 기본 원리를 학습한다.
Python의 RPi.GPIO 모듈을 사용해
- 출력 핀 제어 (GPIO.OUT)
- LED 점멸 제어 (HIGH / LOW)
- 안전한 종료 처리 (try-except-finally)
를 구현한다.
2. 사용 환경
항목내용
| 기기 | Raspberry Pi 4B |
| OS | Raspberry Pi OS (Bookworm) |
| 언어 | Python 3 |
| 라이브러리 | RPi.GPIO |
| 회로 구성 | GPIO 23번 핀 → 저항(220Ω) → LED → GND |
3. 회로 연결
GPIO23 ───[저항 220Ω]───► LED(+) LED(-) ───► GND
👉 전류 제한용 저항을 반드시 연결해야 함.
저항이 없으면 LED나 GPIO 핀이 손상될 수 있다.
4. 코드 설명
import RPi.GPIO as GPIO import time led_pin = 23 # LED 핀 번호 (BCM 모드 기준) GPIO.setmode(GPIO.BCM) GPIO.setup(led_pin, GPIO.OUT) try: while True: GPIO.output(led_pin, GPIO.HIGH) # LED ON time.sleep(1) GPIO.output(led_pin, GPIO.LOW) # LED OFF time.sleep(1) except KeyboardInterrupt: print("사용자에 의해 종료됨 (Ctrl+C 입력)") finally: GPIO.cleanup() print("GPIO 핀 정리 완료")
5. 코드 구조 해설
구문설명
| GPIO.setmode(GPIO.BCM) | Broadcom(BCM) 핀 번호 체계 사용 |
| GPIO.setup(led_pin, GPIO.OUT) | LED 핀을 출력용으로 설정 |
| GPIO.output(led_pin, GPIO.HIGH) | 핀에 3.3V 출력 → LED 켜짐 |
| GPIO.output(led_pin, GPIO.LOW) | 0V 출력 → LED 꺼짐 |
| time.sleep(1) | 1초 지연 (깜빡임 간격) |
| try~except KeyboardInterrupt | Ctrl+C 눌러 종료 시 예외 처리 |
| GPIO.cleanup() | 모든 핀 초기화 후 안전하게 종료 |
6. 실행 결과
터미널에서 아래 명령으로 실행:
sudo python3 led_basic_test1.py
LED가 1초 간격으로 켜졌다가 꺼지는 동작을 반복한다.
Ctrl + C 입력 시 아래 메시지 출력 후 안전 종료된다:
^C사용자에 의해 종료됨 (Ctrl+C 입력) GPIO 핀 정리 완료
7. 에러 로그 해석 (참고)
Traceback (most recent call last): File "/home/pi/work/led/led_basic_test1.py", line 14, in <module> time.sleep(1) KeyboardInterrupt
- 이는 오류가 아닌 정상적인 종료 신호다.
- KeyboardInterrupt는 사용자가 Ctrl+C를 눌렀다는 의미이며,
예외처리(except KeyboardInterrupt)를 추가하면 깔끔하게 처리된다.
8. 개선 포인트
- LED 밝기 제어 : PWM 기능(GPIO.PWM) 활용
- 버튼 연동 : 입력 핀(GPIO.IN)을 추가해 토글 제어 구현
- 다중 제어 : 여러 개의 LED를 동시에 깜빡이게 설정 가능
9. 마무리 정리
항목핵심 요약
| 실습 목적 | Python으로 GPIO 출력 제어 학습 |
| 주요 개념 | HIGH / LOW, BCM 모드, 예외 처리 |
| 실행 종료 | Ctrl+C → KeyboardInterrupt → GPIO 정리 |
| 응용 방향 | 버튼 제어, PWM, 센서 연동 등 |
MQTT 구독자(Subscriber) - 라즈베리파이 연동
이 예제는 라즈베리파이와 자바를 이용한 MQTT 통신 중 구독(Subscribe) 동작을 구현한 코드이다.
즉, 브로커에 접속해서 특정 토픽(topic)을 구독하고,
그 토픽으로 메시지가 들어올 때마다 자동으로 메시지를 받아 출력하는 구조이다.
기본 개념 정리
용어설명
| MQTT | 경량 메시징 프로토콜. IoT 기기 간 통신에 자주 사용됨. |
| 브로커(Broker) | 메시지를 중계하는 서버 (ex. Mosquitto). |
| Publisher | 메시지를 발행하는 쪽 (예: 센서 데이터 보내기). |
| Subscriber | 메시지를 구독하고 수신하는 쪽 (예: LED ON/OFF 명령 받기). |
| Topic | 메시지가 오가는 “채널” 이름. |
Publisher(발행자) → [Broker(브로커)] → Subscriber(구독자)
- 발행자는 특정 topic 으로 메시지를 보냄.
- 브로커는 그 메시지를 받아 구독 중인 클라이언트에게 전달.
- 구독자는 메시지가 들어올 때마다 자동으로 콜백(callback)을 실행함.
package basic;
import java.util.Scanner;
import org.eclipse.paho.client.mqttv3.*;
// MQTT 클라이언트(Subscriber)
// - 특정 토픽을 구독하고 메시지가 도착할 때마다 자동으로 처리
public class MqttSubClientWithRaspberry {
private MqttClient mqttClient;
private MqttConnectOptions mqttOptions;
// 생성자 : 브로커 서버 주소와 클라이언트 ID 설정
public MqttSubClientWithRaspberry(String server, String clientId) {
mqttOptions = new MqttConnectOptions();
mqttOptions.setCleanSession(true); // 세션 초기화
mqttOptions.setKeepAliveInterval(60); // ping 주기(초 단위)
try {
mqttClient = new MqttClient(server, clientId);
// 콜백 등록 (메시지 수신 이벤트 처리)
mqttClient.setCallback(new MqttCallback() {
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
System.out.println("=============== 메시지 도착 ===============");
System.out.println("Topic: " + topic);
System.out.println("Message ID: " + message.getId());
System.out.println("Payload: " + new String(message.getPayload()));
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
// 구독자는 보통 사용하지 않음
}
@Override
public void connectionLost(Throwable cause) {
System.out.println("연결이 끊어졌습니다: " + cause.getMessage());
}
});
// 브로커 연결 시도
mqttClient.connect(mqttOptions);
System.out.println("✅ MQTT Broker 연결 성공");
} catch (MqttException e) {
e.printStackTrace();
}
}
// 구독 신청 메서드
public void subscribe(String topic) {
try {
if (topic != null) {
mqttClient.subscribe(topic, 0); // QoS = 0 (가장 단순한 수준)
System.out.println("📡 구독 시작: " + topic);
}
} catch (MqttException e) {
e.printStackTrace();
}
}
// 메인 (테스트용)
public static void main(String[] args) {
// 브로커 주소와 클라이언트 ID 설정
MqttSubClientWithRaspberry client =
new MqttSubClientWithRaspberry("tcp://192.168.14.116:1883", "my1");
Scanner key = new Scanner(System.in);
System.out.println("1. led 켜기");
System.out.println("2. led 끄기");
System.out.print("원하는 작업 선택 >>> ");
int val = key.nextInt();
String msg = (val == 1) ? "led_on" : "led_off";
// 토픽 구독
client.subscribe("home/livingroom/light");
}
}
코드 설명
구분코드설명
| 1. 옵션 설정 | mqttOptions.setCleanSession(true) | 이전 세션 기록 초기화 (재접속 시 새로 시작) |
| mqttOptions.setKeepAliveInterval(60) | 브로커와 60초마다 ping 주고받음 | |
| 2. 콜백 등록 | mqttClient.setCallback() | 메시지가 도착하면 자동 실행될 이벤트 등록 |
| 3. messageArrived() | 메시지 수신 시 동작 (topic, payload 출력) | |
| 4. connect() | 브로커 서버(tcp://IP:1883)에 연결 | |
| 5. subscribe() | 특정 토픽 구독 | |
| 6. main() | 사용자의 선택(LED ON/OFF)에 따라 동작 결정 |
핵심 요약
항목역할
| MqttClient | MQTT 통신 주체 (Publisher or Subscriber 가능) |
| MqttConnectOptions | 브로커 접속 설정 (세션, ping 등) |
| MqttCallback | 이벤트 처리 (메시지 수신 시 자동 호출) |
| subscribe() | 브로커로부터 메시지 수신 신청 |
| messageArrived() | 메시지 수신 후 실행되는 콜백 |
'HDC 학습일지' 카테고리의 다른 글
| 2025-10-20(파이썬 (스레드, pub,sub통합), 자바 (pub,sub 통합)) (0) | 2025.10.21 |
|---|---|
| 스마트 빌딩 관리 시스템 (미니 프로젝트) (0) | 2025.10.20 |
| 2025-10-16(서브모터 제어, MQTT 통신 (자바)) (0) | 2025.10.16 |
| 2025-10-15(라즈베리파이-2, PWM (0) | 2025.10.16 |
| 2025-10-14(라즈베리파이) (0) | 2025.10.15 |