투케이2K

185. (TWOK/LOGIC) [Aws] IoT 디바이스 기기 AWS 플릿 프로비저닝 수행 후 자동 펌웨어 업데이트 여부 체크 및 OTA 수행 로직 본문

투케이2K 로직정리

185. (TWOK/LOGIC) [Aws] IoT 디바이스 기기 AWS 플릿 프로비저닝 수행 후 자동 펌웨어 업데이트 여부 체크 및 OTA 수행 로직

투케이2K 2026. 5. 9. 14:28
728x90
반응형

[로직 정리]

정리 로직 : AWS / IoT / OTA

제 목 : [Aws] IoT 디바이스 기기 AWS 플릿 프로비저닝 수행 후 자동 펌웨어 업데이트 여부 체크 및 OTA 수행 로직

 

[설 명]

// --------------------------------------------------------------------------------------
[사전) 설정 및 정보 확인 사항]
// --------------------------------------------------------------------------------------

1. 제 목 : [Aws] IoT 디바이스 기기 AWS 플릿 프로비저닝 수행 후 자동 펌웨어 업데이트 여부 체크 및 OTA 수행 로직


2. 테스트 환경 : Aws / IoT / Device / OTA


3. 사전) 👉 AWS IoT Core 간단 설명 : 

  >> AWS IoT 는 IoT 디바이스를 다른 디바이스 및 AWS 클라우드 서비스에 연결하는 클라우드 서비스를 제공합니다.

  >> 디바이스가에 연결할 수 있는 경우 AWS IoT는 AWS 가 제공하는 클라우드 서비스에 디바이스를 AWS IoT 연결할 수 있습니다.

  >> AWS IoT Core 메시지 브로커는 MQTT 및 MQTT over WSS 프로토콜을 사용하여 메시지를 게시하고 구독하는 디바이스 및 클라이언트를 지원합니다. 
  
    - HTTPS 프로토콜을 사용하여 메시지를 게시하는 디바이스와 클라이언트도 지원합니다.


4. 사전) 👉 IoT 장비 간략 설명 : 

  >> IoT 장비 (사물인터넷, Internet of Things Device) 는 인터넷에 연결되어 데이터를 수집·전송·처리하고, 다른 시스템이나 사람과 상호작용하는 물리적 장치를 말합니다.

  >> IoT 장비의 기본 구성요소 : 

    - 센서 (Sensor) : 온도, 습도, 조도, 가속도, 압력, 위치(GPS) 등 주변 환경이나 상태를 측정
    - 액추에이터 (Actuator) : 명령에 따라 물리적 동작 수행
    - 프로세서 / MCU : 센서 데이터 처리 및 로직 수행
    - 통신 모듈 : 데이터를 외부로 전송하거나 명령을 수신
    - 전원 : 배터리, 어댑터, 태양광 등

  >> IoT 장비 주요 특징 : 

    - 실시간 데이터 수집
    - 원격 모니터링 및 제어
    - 자동화 및 지능화
    - 24/7 지속적 운영
    - 대규모 확장 가능성(수천~수백만 대)

  >> IoT 장비의 동작 흐름 예시 : 

    - 센서 → IoT 장비 → 네트워크 → 서버/클라우드 → 분석/저장 → 사용자 앱

// --------------------------------------------------------------------------------------






// --------------------------------------------------------------------------------------
[로직 설명]
// --------------------------------------------------------------------------------------

👉 사전) 해당 로직 구현 이유

  >> 디바이스 기기 양산 생산 후 펌웨어 버전이 변경 될 경우 자동으로 기기 등록 시 필수 펌웨어 버전으로 업데이트 하기 위함

  >> ✔️ 해당 로직을 수행 하기 전 업데이트 펌웨어 BIN 파일은 S3 에 업로드해 놓은 상태


1. ✅ 디바이스 기기에 클레임 인증서 내장 후 AWS IoT Core 플릿 프로비저닝 수행 실시

  >> 클레임 인증서를 사용해 AWS IoT Core 연결 수행

  >> 임시 사물 인증서 발급 요청 수행

  >> 템플릿 등록 요청 수행 

    - 임시 사물 인증서에 정책 연결 됨

  >> AWS IoT Core 연결할 ThingName 발급 완료

  >> 기존에 연결 된 AWS IoT Core 연결 해제 수행

  >> 발급 된 사물 인증서를 사용해 AWS IoT Core 연결 수행 실시


2. ✅ 디바이스 기기 프로비저닝 완료 후 기기 등록 완료 요청 named shadow 생성 수행

  >> 디바이스 기기는 프로비저닝 완료 이후 데이터 송수신을 하기 위한 named shadow 순차적 생성

  >> 👉 펌웨어 업데이트 감지를 위한 /job 토픽도 구독 수행

    - 원격 작업 다음 실행해야 할 단일 Job 알림 수신 notify-next 토픽 : $aws/things/{thingName}/jobs/notify-next
    - 원격 작업 전체 Pending Job 목록 알림 수신 notify 토픽 : $aws/things/{thingName}/jobs/notify

  >> 최종 기기 등록 완료 요청을 의미하는 REGIST Shadow 생성 수행


3. ✅ 디바이스 기기 등록 완료 요청 이후 업데이트 할 펌웨어 버전이 있는 지 체크 수행 shadow reported 수행

  👉 Shadow 전송 페이로드 예시 
    {
      "state": {
        "reported": { 
          "procedure": "FIRMWARE.UPDATE",
          "version": "1.0.2" // 현재 기기 펌웨어 버전
        }
      }
    }


4. ✅ AWS IoT Core 룰엔진에서 FIRMWARE.UPDATE 명령으로 들어온 이벤트 감지 후 람다 함수에서 S3 에 올라가 있는 펌웨어 파일과 버전 비교 수행


5. ✅ [IF] 해당 펌웨어 버전이 최신 버전 또는 업데이트할 필요가 없는 경우 람다 함수 로직 처리 종료 수행


6. ✅ [ELSE] 해당 펌웨어 버전이 최신 버전으로 업데이트 필요가 있는 경우 특정 사물에 createJob 생성 및 펌웨어 업데이트 요청 수행


7. ✅ 디바이스 기기는 구독하고 있는 /job 토픽을 통해 펌웨어 업데이트 명령이 내려온 경우 OTA 수행 실시


6. createJob 펌웨어 업데이트 잡 생성 자바스크립트 예시 코드 첨부 : 

  <script src="https://code.jquery.com/jquery-latest.min.js"></script>
  <script src="https://sdk.amazonaws.com/js/aws-sdk-2.1416.0.min.js"></script>

  const region = 'ap-northeast-2'; // [AWS 리전]
  const accessKeyId = 'AK..A6'; // [IAM 액세스 키]
  const secretAccessKey = 'mP..5J'; // [IAM 시크릿 키]

  var innerFunction = null; // [내부 클로저 선언 실시]

  var THING_NAME = "TWOK_1234"; // 사물 명칭 이름 : Thing Arn 조회에 사용
  var THING_ARN = ""

  var DEVICE_TYPE = "DEVICE"
  var DEVICE_MODEL = "camera"
  var DEVICE_BRAND = "TWOK_COMPANY"
  var FRM_URL = "https://service.com/TEST_Firmware/V1.0.40_Bin"
  var FRM_MD5 = "e76052c97"
  var FRM_VERSION = "1.0.1"

  var JOB_ID = function(){ // ✅ 리턴 JobID : 호출 > JOB_ID()
    return `DEVICE_OTA_JOB_TEST_${THING_NAME}_1`
  }

  var JOB_DOC = function(){ // ✅ 리턴 JobDoc 문서 : 호출 > JOB_DOC()
    return `{
              "operation": "UPDATE",
              "description": "Request Update Firmware",
              "target": [
                {
                  "deviceType": "${DEVICE_TYPE}",
                  "deviceThingList": [
                    "${THING_NAME}"
                  ],
                  "version": "${FRM_VERSION}",
                  "model": "${DEVICE_MODEL}",
                  "brand": "${DEVICE_BRAND}",
                  "firmwareUrl": "${FRM_URL}",
                  "firmwareFileMd5": "${FRM_MD5}"
                }
              ],
              "jobExecutionsRolloutConfig": {
                "maximumPerMinutes": 10
              }
            }`
  }


  window.onload = async function() {

    // -----------------------------------------
    // [초기 변수 초기화]
    // -----------------------------------------
    innerFunction = null;


    // -----------------------------------------
    // [AWS.config 지정]
    // -----------------------------------------
    // IAM 계정 정보를 사용해 AWS.config 정보 업데이트 수행
    // -----------------------------------------      

    AWS.config.update({
      region: region,
      accessKeyId: accessKeyId,
      secretAccessKey: secretAccessKey
    });



    // -----------------------------------------
    // [AWS.Iot 객체 생성]
    // -----------------------------------------
    const aws = new AWS.Iot();


    // -----------------------------------------
    // [내부 클로저 함수 정의]
    // -----------------------------------------
    innerFunction = async function() {

      try {
        
        // -----------------------------------------
        // [Thing Info 요청 파라미터 생성]
        // -----------------------------------------
        const thing_param = {
          thingName: THING_NAME // 사물 명칭
        };


        // -----------------------------------------
        // [DescribeThing] : Aws Iot Core 에 생성 된 Thing 사물 정보 조회
        // -----------------------------------------
        // AWS 참고 사이트 : https://docs.aws.amazon.com/ko_kr/iot/latest/apireference/API_DescribeThing.html
        // -----------------------------------------
        const [thing_err, thing_res] = await aws.describeThing( thing_param ).promise()                
          .then(data => [null, data])
          .catch(error => [error, null]);

        if (thing_err) {
          console.error("[describeThing] : [Error] : ", thing_err);
        } else {

          // ---------------------------------------------
          // ✅ [Thing Info 로그 출력 예시 첨부]
          // ---------------------------------------------
          /*
          {
            "defaultClientId": "TWOK_1234",
            "thingName": "TWOK_1234",
            "thingId": "b6..854",
            "thingArn": "arn:aws:iot:ap-northeast-2:123456789012:thing/TWOK_1234",
            "thingTypeName": "DEVICE",
            "attributes": {},
            "version": 1,
            "billingGroupName": null
          }
          */              
          // ---------------------------------------------

          if (thing_res == null || thing_res == undefined || String(typeof thing_res).toLowerCase() == "undefined" || JSON.stringify(thing_res) == "null" || thing_res == "") {                    
            console.error("[describeThing] : [Error] : thing info is null");
          }
          else {
            console.log("[describeThing] : [Success]");
            
            if (thing_res.hasOwnProperty("thingArn") == true){
              THING_ARN = thing_res.thingArn; // ✅ Set Thing ARN


              // [테스트 동적 데이터 변경]
              /*
              THING_NAME = "TWOK1234";
              DEVICE_TYPE = "DEVICE_TEST"
              DEVICE_MODEL = "testModel"
              DEVICE_BRAND = "2K"
              FRM_URL = "https://test.com"
              FRM_MD5 = "abcd"
              FRM_VERSION = "1.0.1" 
              // */


              const JOB_DOC_JSON = JSON.parse(JOB_DOC()); // ✅ Parse JobDoc


              // -----------------------------------------
              // [create Job 요청 파라미터 생성]
              // -----------------------------------------
              const job_param = {
                jobId: JOB_ID(),
                targets: [THING_ARN],   // 작업을 수행할 Thing 또는 Thing Group
                document: JSON.stringify(JOB_DOC_JSON), // ✅ document 필드는 string 타입으로 정의되어 있습니다
                description: "Firmware Update Job",
                targetSelection: "SNAPSHOT" // 또는 CONTINUOUS
                /*
                , timeoutConfig: { // 디바이스가 Job 을 IN_PROGRESS 상태로 만든 후 일정 시간이 자났음에도 SUCCEEDED , FAILED 상태가 업데이트 되지 않으면 자동 TIME_OUT 상태로 전환 기능
                    inProgressTimeoutInMinutes: 60
                }
                // */

              };


              console.log("job_param : ", JSON.stringify(job_param));


              // -----------------------------------------
              // [createJob] : Aws Iot Core 에 원격 작업 생성 수행
              // -----------------------------------------
              // AWS 참고 사이트 : https://docs.aws.amazon.com/iot/latest/apireference/API_CreateJob.html
              // -----------------------------------------
              const [job_err, job_res] = await aws.createJob( job_param ).promise()                
                .then(data => [null, data])
                .catch(error => [error, null]);


              if (job_err) {
                console.error("[createJob] : [Error] : ", job_err);
              } else {
                // ---------------------------------------------
                // ✅ [Create Job 로그 출력 예시 첨부]
                // ---------------------------------------------
                /*
                {
                  "jobArn": "arn:aws:iot:ap-northeast-2:123456789012:job/DEVICE_OTA_JOB_TEST_TWOK_1234_1",
                  "jobId": "DEVICE_OTA_JOB_TEST_TWOK_1234_1",
                  "description": "Firmware Update Job"
                }
                */              
                // ---------------------------------------------

                if (job_res == null || job_res == undefined || String(typeof job_res).toLowerCase() == "undefined" || JSON.stringify(job_res) == "null" || job_res == "") {                    
                  console.error("[createJob] : [Error]");

                }
                else {
                  console.log("[createJob] : [Success]");
                }

              }

            }
            else {
              console.error("[describeThing] : [Error] : ThingArn Is Null");
            }

          }               

        }

      }
      catch(exception){
        console.error("[innerFunction] : [Exception] : ", exception);
      }

    };



    // -----------------------------------------
    // [내부 클로저 함수 호출]
    // -----------------------------------------
    innerFunction();

  }

// --------------------------------------------------------------------------------------






// --------------------------------------------------------------------------------------
[참고 사이트]
// --------------------------------------------------------------------------------------

▶️ [AWS 원격 펌웨어 업데이트 OTA 수동 job 생성 및 특정 사물 notify 펌웨어 업데이트 요청 방법 정리]

https://kkh0977.tistory.com/8159

https://blog.naver.com/kkh0977/223944636139?trackingCode=blog_bloghome_searchlist


▶️ [자바스크립트 AWS STS 임시 자격 증명 사용해 S3 Get PreSignedUrl 프리 사인 URL 주소 생성]

https://kkh0977.tistory.com/8151

https://blog.naver.com/kkh0977/223938740405?trackingCode=blog_bloghome_searchlist


▶️ [Aws Iot Core] Fleet provisioning 플릿 프로비저닝 설명 및 동작 프로세스 정리

https://kkh0977.tistory.com/7439

https://blog.naver.com/kkh0977/223691943757?trackingCode=blog_bloghome_searchlist


▶️ [Aws Iot Core] Fleet provisioning 플릿 프로비저닝 수행 방법 정리 - 클레임 인증서 , 신뢰할 수 있는 사용자

https://blog.naver.com/kkh0977/223779257161?trackingCode=blog_bloghome_searchlist


▶️ [업무 이슈] IoT 장비 등록 및 운영 시 하나의 WIFI 와이파이 에 너무 많은 기기를 연결해 통신 속도 저하 문제 이슈

https://kkh0977.tistory.com/8798

https://blog.naver.com/kkh0977/224274829743

// --------------------------------------------------------------------------------------
 
728x90
반응형
Comments