Notice
Recent Posts
Recent Comments
Link
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
Archives
Today
Total
관리 메뉴

memo6759 님의 블로그

2025-10-17 [라즈베리파이 mqtt ,쓰레드(상속,이너클래스)] 본문

HDC 학습일지

2025-10-17 [라즈베리파이 mqtt ,쓰레드(상속,이너클래스)]

heewon09 2025. 10. 19. 18:31

익명 이너클래스 

익명 이너 클래스란?

이름이 없는 클래스(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() 메시지 수신 후 실행되는 콜백