feat: publish NIRO Gen5W research overview and reviewed source examples

This commit is contained in:
seo committed 2026-11-02 09:59:38 +09:00
commit ccad0ed9f3
23 files changed
+1279

No files matched your search

+39
View File
@@ -0,0 +1,39 @@
# 구조와 경계
이 문서는 개인 접속 주소나 운영 비밀값 없이 전체 설계를 설명합니다. 본 공개본에 모든 구성 요소가 구현·포함돼 있다는 뜻은 아닙니다.
## 데이터가 흐르는 경로
```text
차량 ECU / MICOM / HSCAN
↓ 원래 헤드유닛이 수신하는 정보
Android 4.4 계열 서비스·Binder·순정 앱·내비 native
├─ 순정 화면: 날씨 / 캘린더 / 스포츠 / RPM / 위치공유
├─ 제한된 HTTPS 연동 → 개인 백엔드 → 외부 데이터 공급자
└─ 검증된 변화값 → MQTT → Home Assistant / 모니터 / 차계부
```
핵심은 Android의 root 권한과 차량 ECU의 권한을 구분하는 것입니다. 헤드유닛에서 root를 얻어도 모든 차량 신호가 수신되는 것은 아니며, 모든 ECU 제어가 가능한 것도 아닙니다.
## 세 가지 코드 계층
| 계층 | 역할 | 공개본의 범위 |
|---|---|---|
| 순정 앱과 ODEX | 화면·요청·callback·서비스 진입 | 설명만, 제조사 원본·수정 전체 앱 제외 |
| 내비 네이티브 | 지도·경로 계산·교통·카메라·렌더링 | 설명과 과거 단일 변경 생성기 예제 |
| 독립 수집·변환 코드 | 수신 검증·요청 제어·MQTT·서버 계약 변환 | 검토한 일부 소스와 합성 시험 |
운영 배포는 동일 버전 확인과 해시 검증을 거친 작은 변경을 우선했습니다. 일부 앱은 원본 APK를 유지하고 ODEX payload를 bind하는 방식, 내비는 해당 엔진에 맞는 제한된 native 변경을 사용했습니다. 이 방법도 버전 의존성이 있으므로 범용 설치법이 아닙니다.
## 원천값과 표시값
- RPM decoder는 도착한 프레임을 검증한 뒤 callback을 호출합니다. 이벤트 반영은 화면 렌더링 시간이 0이라는 뜻이 아닙니다.
- 내비 차속 보정은 내비의 내부 소비값을 바꾸는 것입니다. 차량 ECU·계기판·OBD의 원시 속도를 변경하지 않습니다.
- MQTT는 이미 확인한 값을 운반하는 수단입니다. 초기값이나 잘못된 해석을 MQTT가 정답으로 만들어 주지 않습니다.
- 연결이 끊긴 실시간 센서와 마지막 관측값은 서로 구분해야 합니다. 오래된 속도·기어·시동값을 현재 제어 판단에 쓰지 않습니다.
## 서버 인증과 저장
운영 서버는 차량 인증, 관리자 세션, CSRF, 명령 상태기계, 수신자별 공유 링크와 만료·폐기를 따로 관리합니다. 실제 키·개인정보·DB·원문 요청 로그는 공개하지 않습니다. 백엔드 변환기는 정식 서비스 가입·결제·차량 인증을 대신하지 않으며, SOS·결제의 가짜 성공을 제공하지 않습니다.
헤드유닛의 전원이 완전히 꺼져 Android와 네트워크가 정지하면 이 경로로 원격 명령을 받을 수 없습니다. 별도 저전력 수신기와 검증된 wake 연동은 독립적인 하드웨어 과제입니다.
+42
View File
@@ -0,0 +1,42 @@
# 기능별 구현과 확인 범위
기준: 2026-11-01 운영 기록. 이 표는 전체 개인 프로젝트의 성과이며, 해당 기능의 완성 소스·배포물이 모두 공개돼 있다는 뜻은 아닙니다. `실차 확인`도 표에 적힌 조건과 대상에 한정됩니다.
| 기능 | 구현·관측한 내용 | 남은 한계 |
|---|---|---|
| Wi-Fi·관리 경로 | 순정 STA 연결·설정 저장·재부팅 자동 연결, SSH·Tailscale 운영 | 다른 차종·공유기 조합은 미검증 |
| 순정 Wi-Fi 메뉴 | 순정 설정 타일·Wi-Fi 탭 관련 분기만 제한적으로 복원 | 전역 feature 판정 위장 안 함 |
| 날씨·대기질 | 홈·상세·예보·갱신, 관측과 모델 fallback 구분 | 공급자 coverage·갱신 주기 의존 |
| 웰컴 날씨 TTS | 날씨 전용 대기 경로와 실행 시간대 보정, 야간 냉간 부팅 출력 | 뉴스 브리핑 구현 아님 |
| HA 캘린더 | 읽기 전용 일정 변환·순정 목록·수동 갱신 | 일정 필드별 모든 현장 조합은 미검증 |
| 스포츠 | 지원 6종목의 팀 데이터·순정 parser·목록 | 현재 시즌·경기·순위는 공급자 플랜 의존, 골프·크리켓 미공급 |
| 위치공유 | 번호 정규화·수신자별 링크·기존 링크 재사용·신규 SMS·부분 실패 격리·개별 해지 | 최신 GPS 대기·Binder 재연결 등 지속 개선 |
| 공유 웹 화면 | 같은 페이지의 위치·허용 차량정보·지도·이동 궤적 갱신 | 링크 수명·권한을 넘는 정보는 미공개 |
| 목적지 전송 | 주소 검색→대기열→순정 POI→최종 ACK | Android·네트워크가 꺼지면 수신 불가 |
| 순정 진단 | 12개 고유 ECU와 읽기 보고 경로 확인 | 외부 장비 충돌 방지 유지, 정비 쓰기 제외 |
| 원격제어 | 확인된 시동·도어 명령의 순정 실행과 최종 응답 연계 | 모든 명령 검증 아님, 완전 전원 차단 뒤 제어 불가 |
| HA·MQTT | 의미를 확인한 센서·변화값 전달, 잘못된 초기값 발행 제한 | 공용 getter가 모두 해당 차량의 유효 센서는 아님 |
| 디지털 액자 | 순정 표시 경로·이미지 리사이즈·서로 다른 화면 비율 대응 | 두 화면에 같은 픽셀 배열을 강제로 맞추지 않음 |
| 지도 RPM | 실제 수신 RPM/1,000과 소수 한 자리, 주·야간 색상 | 연료 %나 ECU 제어와 별개 |
| 내비 차속 | 내비 내부 한 입력 경계에서 1 이상일 때 -1, 0 유지 | ECU 원시 속도 변경 아님 |
| 구간 평균속도 | 화면 표시 보정, 계산·초과 판단 경로 보존 | 실제 구간 진입의 모든 화면 회귀는 미완료 |
| 자동 축척 | 50·75·100·150·200·300·400·600·800 m | 일부 단계의 실제 렌더링·라벨 확인, 전 화면 검증 아님 |
| 경치 좋은 길 | 설치 지도 DB·사진·기존 scene을 이용해 메뉴·목록·미리보기 복원 | 별도 온라인 추천 경로가 아님 |
| 회피 옵션 | 고속도로·페리·유료도로·터널·비포장 회피 메뉴와 OEM 비용 경로 연결 | 각 도로 유형의 비교 주행 시험은 미완료 |
| 지도·엔진 | 신지도와 맞는 엔진으로 HAFP 경로 계산 crash 대응 | 지도만 바꿔도 항상 호환된다는 뜻 아님 |
| DMB/TPEG | PCBER/FIC·서비스 재연결·개별 값 보존 경계 보정 | 방송 지연·수신 음영·미지원 도로는 남음 |
| 후면 카메라 | 일치 조건을 만족하는 기존 후면 DB 속성 보존 | 방송에 없는 신규 rear 속성은 추정하지 않음 |
## 보류·미구현·미지원
| 항목 | 상태와 이유 |
|---|---|
| Naver 경로 완전 이식 | 무기한 보류. 단일 geometry의 지도 link 변환과 parser 시험은 있었지만, 순정 지도 안내·옵션·재탐색 전체는 미완료 |
| IP 교통정보 | 무기한 보류. 계약과 설치 지도 식별자 변환을 연구했으나 전체 coverage·실차 표시 완료 아님 |
| 무선 AA/CarPlay | 순정 비활성. 외부 구현과 니로 원본의 호환성 분석 단계, 실연결 성공 아님 |
| 인터넷 STA+projection AP 동시 사용 | 미구현·실차 검증 필요 |
| ECO 주 경로 | 미적용. 한국형 비용 factory·연료 표 경로가 연결되지 않아 메뉴 노출만으로 해결 불가 |
| 실제 연료 잔량 % | 미확인. 고정 getter·미수신값을 잔량으로 환산하지 않음 |
| DTC 삭제·강제 액추에이터·ECU 코딩 | 운영 기능으로 제공하지 않음 |
| 실제 CarPay 결제 | 구현하지 않음. 가맹·차량·결제 인증을 로컬 성공 응답으로 대체하지 않음 |
| MCU 내부 전체 역분석 | 완료 아님. Android/native 경계와 암호화된 MCU 실행 코드를 구분 |
+37
View File
@@ -0,0 +1,37 @@
# 공개 범위와 출처
## 별도 공개 저장소
기존 비공개 운영 저장소의 `.git`·이력·설정·리모트를 복사하지 않고 새 이력으로 시작합니다. 이 저장소를 운영 배포의 기준선으로 사용하지 않습니다.
## 초기 공개 소스의 출처
| 공개 모듈 | 성격 | 시험 입력 |
|---|---|---|
| `HscanRpmDecoder` | 개인 프로젝트에서 작성한 수신 프레임 검증·RPM 해석 코드 | 프로그램으로 생성한 합성 프레임 |
| `WeatherRefreshGate` | 직접 작성한 요청 admission·재사용·실패 backoff 상태기계 | 합성 monotonic 시각 |
| `WeatherRefreshCounters` | 직접 작성한 요청/완료 계수와 파일 교체 로직 | 시험 임시 디렉터리 |
| `NiroMqttKeepalive` | 직접 작성한 MQTT keepalive 시간 추적 | 합성 시각 |
| `NiroRawSnappy` | 직접 작성한 raw Snappy literal encoder | 합성 바이트열 |
| 과거 V038 차속 생성기 | 입력 해시·명령 창·변경 범위를 검사하는 직접 작성한 도구 | 합성 이미지, 제조사 원본 없음 |
Java namespace는 원래 코드의 `com.chaegeon.niro`를 유지합니다. 이는 운영 서버 주소나 차량 식별값이 아닙니다. 시험의 CAN envelope·메시지 번호·단위는 설명을 위한 계약 정보이며 실차 capture 전체를 포함하지 않습니다.
내비 예제에는 호환성 검사용 짧은 명령 값과 직접 작성한 wrapper가 있습니다. 제조사 라이브러리 자체·디컴파일 전체·지도·완성 패치 바이너리는 제공하지 않습니다. 대상 파일을 소유한다는 사실만으로 모든 변경·배포 권한이 생기는 것은 아니므로 적용 가능성과 이용 조건은 각자가 확인해야 합니다.
외부 프로젝트는 관련 링크로 소개할 뿐, NEMESIS·Leafia·gen5w-utils의 소스·바이너리를 초기 공개본에 가져오지 않았습니다. 향후 외부 코드를 추가하면 원래 라이선스와 변경·출처를 별도로 기록해야 합니다.
## 제외한 것
- 제조사 펌웨어·지도·APK·ODEX·라이브러리 원본 및 수정 전체 배포물
- 차량의 실제 GPS·주행 기록·전화번호·VIN·차량 고유 식별자
- API 키·비밀번호·SSH 개인키·MQTT 인증정보·공유 원문 token
- 실차·운영 서버의 원문 로그·DB·백업·내부 주소·배포 설정
- 차량 자동 접속·재부팅·실제 명령 실행·ECU 쓰기 기능
- 이전 비공개 Git 이력과 운영 배포 파일
## 공개 검사
`tools/check_publication.py`는 공개 허용 파일 목록과 기본 비밀값·금지 산출물을 검사합니다. Git이 초기화돼 있으면 추적 파일과 이력의 정체성도 확인합니다. 이 검사는 모든 개인정보·저작권·보안 문제를 자동 판별하는 감사가 아닙니다.
새 파일을 추가하려면 내용을 검토한 뒤 허용 목록을 명시적으로 갱신해야 합니다. `.gitignore`만 바꿔 이미 추적된 파일이나 과거 이력이 사라진다고 가정하지 않습니다.
+35
View File
@@ -0,0 +1,35 @@
# 문제를 어떻게 좁혔나
## 1. 센서 이름이 있다고 실제 센서값은 아니다
공용 automotive framework의 수많은 getter 중에는 현재 차종에서 한 번도 갱신되지 않는 초기값과 다른 variant의 값이 있습니다. 전조등·미등의 `0`을 곧바로 꺼짐으로, 후측방의 `-1,-1`을 경고 없음으로 발행하면 그럴듯하지만 틀린 화면이 됩니다.
원천 callback·유효성·단위를 확인하고, 미확인은 미확인으로 남기는 것이 목표입니다. 특히 연료 게이지가 변해도 같은 숫자를 반환하는 getter는 잔량 측정값으로 채택하지 않았습니다. RPM 수신을 성공했다고 연료까지 찾았다고 기록하지 않습니다.
공개한 `HscanRpmDecoder`는 정해진 envelope·길이·XOR·메시지 구조·패딩을 검증한 뒤 RPM을 읽습니다. 이미 받은 바이트를 해석할 뿐, ECU 요청·socket 접속·CAN 송신 기능은 없습니다.
## 2. 교통 packet 도착과 도로별 정보 갱신은 다르다
TPEG packet이 몇 초마다 들어온다는 사실은 모든 도로의 최신 값이 그 간격으로 도착한다는 뜻이 아닙니다. RF lock, PCBER/FIC 확정, 서비스 연결, 내비 callback, 개별 도로의 관측·만료는 따로 봐야 합니다.
운영 보정은 새 유효값으로 갱신하고 누락·무효값으로 유효한 이전 값을 즉시 지우지 않는 것입니다. 보존 TTL은 60분이며, 오래된 값이 실제 현재 교통이라는 뜻은 아닙니다. 미지원 도로·만료 구간은 회색으로 남을 수 있습니다.
후면 카메라도 decoder가 전달하지 않는 rear 속성을 class·개수·거리만으로 추정하지 않습니다. 현재 보존은 검증된 기준 DB와 일치하는 기존 항목에 한정됩니다.
## 3. 지도 파일과 엔진은 독립적으로 바꿔도 되는가
신지도와 구형 엔진의 조합은 부팅·화면 표시에 성공했지만 특정 목적지 계산에서 HAFP node parser crash를 냈습니다. 이후 지도와 맞는 엔진에 기존 변경을 다시 이식하고 같은 실패 요청으로 확인했습니다.
교훈은 `부팅 성공 = 모든 경로 계산 호환`이 아니라는 점입니다. 공개한 과거 V038 차속 생성기는 이 현재 엔진용 설치 파일이 아닙니다. 정확한 입력 해시가 아니면 거부하는 과거 예제로만 제공합니다.
## 4. 외부 경로 geometry와 순정 길안내는 다른 계약이다
Naver 좌표를 목적지·경유점으로 보내면 순정 내비가 자체 경로를 계산할 수는 있지만, 외부 경로를 그대로 안내하는 것은 아닙니다. 설치 지도 link·방향·parcel 경계·연결성·안내 모델이 맞아야 합니다.
과거 한 시험에서 geometry 408점을 241개 RealLink·5,735바이트 순정 응답으로 변환하고 parser 소비를 확인했습니다. 408은 고정 규격이 아니라 그 입력의 표본 수입니다. 이 성과를 임의 경로·실제 안내·주기/이탈 재탐색 완료로 확대하지 않습니다. 관련 실차 개발은 보류돼 있습니다.
## 5. 실패를 숨기는 성공 응답은 해결이 아니다
위치공유는 수신자별 성공·실패를 격리하고, 한 명의 실패로 다른 사람의 정상 링크를 폐기하지 않아야 합니다. 원격 명령은 최종 차량 응답 전까지 성공이 아닙니다. 새 메뉴가 보이는 것과 해당 ECU·경로 엔진이 기능을 지원하는 것도 다릅니다.
이 공개본은 그러한 원칙을 설명하고 일부 순수 로직을 제공합니다. 전체 운영 서버·차량 제어 기능을 배포하는 저장소는 아닙니다.