15.1 AWS MQTT 실습 - sunbang123/Smart_device GitHub Wiki

실습 보고서

AWS 보안 서비스

  1. AWS 인증서
  • AWS 인증서는 AWS IoT 서비스를 사용하여 디바이스를 인증하는 데 사용되는 디지털 인증서
  • 공개키/개인키 쌍으로 구성되어 있으며, 보안 소켓 계층(SSL/TLS) 프로토콜을 통해 디바이스와 AWS IoT 서비스 간의 안전한 통신을 제공
  1. AWS 정책
  • AWS 정책은 AWS 리소스와 서비스에 대한 액세스 제어를 정의하는 규칙의 집합
  • AWS Identity and Access Management (IAM)을 통해 구성할 수 있음.
  • JSON(JavaScript Object Notation) 형식으로 작성됨.
  • 특정 사용자, 그룹, 또는 역할에 대한 허용되거나 거부되는 작업과 리소스를 지정함.
  • 특정 작업에 대한 권한을 부여하거나 제한하여 보안을 강화할 수 있음.

실습1 : ESP32 - AWS MQTT 연결

실습 순서

  1. AWS 콘솔에 접속, 로그인
  2. IoT Core 서비스 접속
  • 모든 서비스 -> 사물인터넷 -> IoT Core
  1. 사물 생성
  • 관리 -> 사물 을 클릭, 사물 생성
  1. 인증키 다운로드
  1. 정책 생성, 연결
  • 보안 -> 정책 탭, 정책 생성 버튼을 클릭
  • 관리 -> 사물 -> YourThingName -> 인증서 에서 인증서 ID를 클릭
  1. 라이브러리 다운
  • 아두이노 라이브러리 관리 에 들어가서 ArduinoJson 과 lwmqtt 를 검색해 다운
  1. 코드 실행, 시리얼 모니터 확인

코드

  • secrets.h파일을 생성.
  • 아래는 코드 내용.
#include <pgmspace.h>

#define SECRET
#define THINGNAME "[사물 이름]"

const char WIFI_SSID[] = "[와이파이 이름]";
const char WIFI_PASSWORD[] = "[와이파이 비밀번호]";
const char AWS_IOT_ENDPOINT[] = "[디바이스 데이터 endpoint].amazonaws.com";  //amazon endpoint

// Amazon Root CA 1
static const char AWS_CERT_CA[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
[CA1 Key]
-----END CERTIFICATE-----
)EOF";

// Device Certificate
static const char AWS_CERT_CRT[] PROGMEM = R"KEY(
-----BEGIN CERTIFICATE-----
[Device 인증서]
-----END CERTIFICATE-----
)KEY";

// Device Private Key
static const char AWS_CERT_PRIVATE[] PROGMEM = R"KEY(
-----BEGIN RSA PRIVATE KEY-----
[Private key]
-----END RSA PRIVATE KEY-----
)KEY";
  • 메인 코드
#include "secrets.h"
#include <WiFiClientSecure.h>
#include <MQTTClient.h>
#include <ArduinoJson.h>
#include "WiFi.h"

// The MQTT topics that this device should publish/subscribe
#define AWS_IOT_PUBLISH_TOPIC   "esp32/pub"
#define AWS_IOT_SUBSCRIBE_TOPIC "esp32/sub"

WiFiClientSecure net = WiFiClientSecure();
MQTTClient client = MQTTClient(256);

void connectAWS()
{
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  Serial.println("Connecting to Wi-Fi");

  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }

  // Configure WiFiClientSecure to use the AWS IoT device credentials
  net.setCACert(AWS_CERT_CA);
  net.setCertificate(AWS_CERT_CRT);
  net.setPrivateKey(AWS_CERT_PRIVATE);

  // Connect to the MQTT broker on the AWS endpoint we defined earlier
  client.begin(AWS_IOT_ENDPOINT, 8883, net);

  // Create a message handler
  client.onMessage(messageHandler);

  Serial.print("Connecting to AWS IOT");

  while (!client.connect(THINGNAME)) {
    Serial.print(".");
    delay(100);
  }

  if(!client.connected()){
    Serial.println("AWS IoT Timeout!");
    return;
  }

  // Subscribe to a topic
  client.subscribe(AWS_IOT_SUBSCRIBE_TOPIC);

  Serial.println("AWS IoT Connected!");
}

void publishMessage()
{
  StaticJsonDocument<200> doc;
  doc["time"] = millis();
  doc["sensor_a0"] = analogRead(0);
  char jsonBuffer[512];
  serializeJson(doc, jsonBuffer); // print to client

  client.publish(AWS_IOT_PUBLISH_TOPIC, jsonBuffer);
}

void messageHandler(String &topic, String &payload) {
  Serial.println("incoming: " + topic + " - " + payload);

//  StaticJsonDocument<200> doc;
//  deserializeJson(doc, payload);
//  const char* message = doc["message"];
}

void setup() {
  Serial.begin(9600);
  connectAWS();
}

void loop() {
  publishMessage();
  client.loop();
  delay(1000);
}

실습 시행착오 및 해결방법

원인 불분명한 문제로 결과가 작동하지 않음.

  1. 핫스팟으로 실행했을때 연결이 안되는 상황 발생.
  • 집 와이파이(5G/2G)를 시도해서 연결해봄.
  • 2G에서 연결이 되는것을 확인.
  1. AWS IoT연결이 안되는 상황 발생 connecting to AWS IOT 이후에 . 만 출력됨.
  • #define THINGNAME 뒤에 사물 이름을 적지 않아서 연결이 안된 것을 확인.
#define THINGNAME "ESP32"
  • 이후에도 계속 연결이 안되서 #define SECRET 뒤에 코드를 작성함.
  1. Acess key 발급
  • AWS Management -> 내 보안 자격 증명 -> 보안 자격 증명 -> 액세스 키 (Access keys) 섹션 -> 액세스 키 만들기 클릭.
#define SECRET "{\"aws_key\":\"[액세스 키 ID]\",\"aws_secret\":\"[시크릿 액세스 키]\",\"aws_region\":\"us-east-2\",\"thing_name\":\"esp32\"}"
  1. 재시도 결과

#define SECRET 은 원래대로 돌려놓음.

설정에서 보안 정보를 IoTSecurityPolicy_TLS12_1_0_2016_01로 바꿔줌.

다른 부분에 이상이 없으므로 wifi를 핫스팟으로 변경해서 재시도.

  1. 재시도 결과

연결 성공!

MQTT 연결 확인

  1. MQTT 테스트창에 esp32 구독 생성
  2. 코드 업로드, 시리얼 모니터 확인
  3. 테스트창에서 MQTT 연결 확인.

실습2 : AWS에 온습도값 보내기.

실습 과정

  1. 코드 업로드, 시리얼 모니터 확인
  2. 테스트창에서 MQTT 연결 확인.
  1. 온습도값이 출력되는지 확인.

온습도값 보내기 성공!

코드

#include "secrets.h"
#include <WiFiClientSecure.h>
#include <MQTTClient.h>
#include <ArduinoJson.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <WiFi.h>

// AWS IoT 설정
#define AWS_IOT_PUBLISH_TOPIC   "esp32/pub"
#define AWS_IOT_SUBSCRIBE_TOPIC "esp32/sub"

// DHT11 센서 설정
#define DHT_PIN 13       // DHT11 데이터 핀
#define DHT_TYPE DHT11  // DHT11 센서

WiFiClientSecure net = WiFiClientSecure();
MQTTClient client = MQTTClient(256);

DHT dht(DHT_PIN, DHT_TYPE);

void connectAWS()
{
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  Serial.println("Connecting to Wi-Fi");

  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }

  // Configure WiFiClientSecure to use the AWS IoT device credentials
  net.setCACert(AWS_CERT_CA);
  net.setCertificate(AWS_CERT_CRT);
  net.setPrivateKey(AWS_CERT_PRIVATE);

  // Connect to the MQTT broker on the AWS endpoint we defined earlier
  client.begin(AWS_IOT_ENDPOINT, 8883, net);

  // Create a message handler
  client.onMessage(messageHandler);

  Serial.print("Connecting to AWS IoT");

  while (!client.connect(THINGNAME)) {
    Serial.print(".");
    delay(100);
  }

  if(!client.connected()){
    Serial.println("AWS IoT Timeout!");
    return;
  }

  // Subscribe to a topic
  client.subscribe(AWS_IOT_SUBSCRIBE_TOPIC);

  Serial.println("AWS IoT Connected!");
}

void publishMessage(float temperature, float humidity)
{
  StaticJsonDocument<200> doc;
  doc["temperature"] = temperature;
  doc["humidity"] = humidity;
  char jsonBuffer[512];
  serializeJson(doc, jsonBuffer);

  client.publish(AWS_IOT_PUBLISH_TOPIC, jsonBuffer);
}

void messageHandler(String &topic, String &payload) {
  Serial.println("incoming: " + topic + " - " + payload);
}

void setup() {
  Serial.begin(9600);
  connectAWS();
  dht.begin();
}

void loop() {
  // 온습도 데이터 읽기
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();
  Serial.println(temperature);
  Serial.println(humidity);
  // 유효한 값인지 확인
  // if (isnan(temperature) || isnan(humidity)) {
  //   Serial.println("Failed to read from DHT sensor!");
  //   return;
  // }

  // 온습도 데이터를 AWS IoT에 전송
  publishMessage(temperature, humidity);

  // AWS IoT 클라이언트 루프
  client.loop();

  delay(1000);
}

느낀점

  • 첫번째 시도때 집 와이파이와 핫스팟 모두 사용해봤지만 connected가 뜨지 않아서 실습을 끝맺지 못한 점이 아쉬웠음.
  • 재시도 하면서 사물 이름을 입력하지 않은 것 처럼 코드 실수로 연결이 안될수 있다는 점을 앞으로 더 유의하자.
  • aws 연결에 필요한 기초 개념(인증서, 보안)을 실습을 통해서 체험할 수 있어서 만족.
  • 실습을 통해 개념에 대한 이해가 쌓일 수 있음.
⚠️ **GitHub.com Fallback** ⚠️