← 목록
기타 2026-07-17 8KB 읽기 8분

크라우니스페이스 RPi 허브 게이트 + 허브 에이전트 (SC1 규격 준수)

개요

crowny-space(:9607) 홈어시스턴트 서버에 RPi5 허브 연동용 게이트웨이 3종 (/api/ingest, /api/commands, /api/hub/register)을 추가하고, SC1/SCMD 규격을 그대로 구사하는 독립 허브 에이전트(RPi허브.한선)를 신규 작성했다. mac에서 HUB_MODE=sim으로 라이브 :9607 서버 대상 E2E를 전부 실측 통과시켰다.

무엇을 했는지

A. 서버 확장 (서버.한선)

  • POST /api/ingest — 본문 = SC1 프레임들(¶ 구분, 게이트웨이 \n제거 함정 대응). 서버가
¶→\n 복원 후 줄 단위 처리. 각 프레임: 체크섬/필드파싱(SC1 규격-v1.md §5·§9와 100% 동일 공식의 최소 이식) → 판정 "티"만 반영, "타/옴/음"은 거부. seq 역행 프레임도 거부. 통과 프레임은 엔티티 상태(quality 포함, extra="q:T/O/A")+로그북(cause:"hub")+ data/수신프레임_N.psv(회전: 3800자 근접 시 다음 N)에 기록. 미등록 엔티티는 자동등록. 응답 {"ok":1,"accepted":N,"rejected":M}.
  • GET /api/commands?hub=<id> — 허브 소유 엔티티의 미전달 SCMD 프레임 반환(¶ 구분),
dequeue 시 전달 표시. 소유 판정은 data/허브맵.psv(hub|entityId).
  • POST /api/hub/register{"hub":"rpi1","entities":"a,b,.."} → 허브맵 갱신.
  • 기존 _처리커맨드(POST /api/command)를 확장: 대상 엔티티가 허브 소유면
data/명령큐.psv에 SCMD를 큐잉(체크섬 포함, 규격 그대로).
  • 버그 발견·수정: 본문추출()"\n\n"(LF LF, curl은 절대 보내지 않음) 또는 첫 "{"
탐색으로만 body를 뽑아, JSON이 아닌 PSV 프레임(SC1|...) 본문을 못 읽는 결함을 발견해 "\r\n\r\n"(실제 HTTP 헤더 종결자) 우선 탐색을 추가(기존 JSON 경로는 그대로 보존, 회귀 없음).
  • 성능/안정성 이슈 발견·완화: 처음에 규격 정본 코덱(규격/센서코드.한선, 27타입
전수+자체시험 110assert 보유)을 서버가 통째로 가져오기했더니 정적 큐브 89894→110022, 문자열 핸들 90% 문턱(432000/480000) 도달을 실측(상시가동 프로세스라 위험). 두 단계로 완화: 1) 정본 코덱의 자체시험() 자동실행을 환경변수("SC1_SELFTEST")=="1"일 때만 돌게 가드 (기본 미실행, SC1_SELFTEST=1 crownyc run ...으로 언제든 ALL_PASS 110/110 재현 가능). 2) 그래도 서버는 규격에 명시된 "체크섬·필드파싱 최소 이식 허용" 조항에 따라 정본 코덱을 import하지 않고 동일 공식(§5)을 서버 내부에 직접 이식(_SC체크섬/_SC디코딩/ _SCMD인코딩/_SC액션유효한가/_SC타입이름) — 최종 큐브 101979(89894 baseline 대비 +12085, STR 경고 소멸 확인). RPi허브.한선은 인코딩측 전체 API가 필요해 정본 코덱을 그대로 import.

B. 허브/RPi허브.한선 (신규)

  • 환경변수 HUB_ID(기본 rpi1)/SPACE_SERVER(기본 http://127.0.0.1:9607)/
HUB_MODE(sim|gpio, 기본 sim)/HUB_CYCLES(기본 0=무한, 시험은 N 지정).
  • 5초 주기 루프: ① 센서 수집(sim=랜덤워크 3종 온도/습도/전력, gpio=GPIO.한선 핀읽기,
RPi 전용 미검증) ② 규격/센서코드.한선 SC인코딩 재사용 ③ 체계()+curl -m 5 POST /api/ingest(¶ 조인) ④ GET /api/commands 폴링→SCMD디코딩→적용(sim=상태 에코, gpio=핀쓰기)→다음 ingest에 반영(light.veranda를 dim(16) 타입으로 echo).
  • seq는 허브/data/<HUB_ID>_seq.txt에 로컬 영속화(재시작해도 서버의 "seq 역행 거부"에
안 걸리게, RPi 실전원 재기동 시나리오 고려).
  • 종료 조건 명시(HUB_CYCLES>0이면 도달 시 종료) — 백그라운드 폭주 금지 가드레일 준수.
  • 허브/배포-rpi.md — RPi5 빌드/배치/systemd 서비스화 runbook(스크립트 아닌 문서).

E2E 실측 결과 (라이브 :9607 대상)

  1. 허브 등록 → sim HUB_CYCLES=3 → {"ok":1,"accepted":3,"rejected":0} × 3회(9프레임)
+ echo 3회(3프레임) = accepted 12(요구 ≥6 충족). /api/entities에 hub 보고값 반영, /api/logbook에 cause:"hub" 다수 확인.
  1. 명령 왕복: POST /api/command(light.veranda, 허브 소유) → /api/commands?hub=rpi1
SCMD 등장 → 허브 다음 사이클이 수신·적용(릴레이상태 갱신)·재보고 → light.veranda entity state가 명령값과 일치(예: 42.0). 두 번째 poll은 빈 응답(dequeue 확인).
  1. 체크섬 훼손 프레임 1개 별도 POST → {"ok":1,"accepted":0,"rejected":1} 확인.
seq 역행 프레임도 동일하게 rejected 처리 확인.
  1. 서버 회귀 8종(health/spaces/entities/logbook/tick/energy/bridge.js/command) 전부
200, launchctl kickstart -k로 재기동 후 허브맵·명령큐·엔티티 상태 전부 파일 기반이라 무손실 복원(추가 부트스트랩 코드 불필요 — 기존 WAL재생 아키텍처 그대로 적용됨) 확인.
  1. 실패 없이 완주 — 서버 원상복구 상황 없었음(백업 4종 보관: 서버.한선.bak-*,
서버.toau.bak-*).

GPIO.한선 실체 판정

/Users/ef/CrownyOS/crownyc/pkg/libs/GPIO.한선순수 시뮬레이션이다. VM 네이티브 GPIO opcode/syscall이 전혀 없고, 맵생성/추가/설정/원소 등 배열·맵 연산만으로 핀 상태를 소프트웨어로 흉내낸다(하드웨어.한선의 신호생성/AND게이트 같은 진짜 논리회로 시뮬레이터와도 다름 — 그냥 상태 저장소). RPi5 실물 GPIO 핀 제어를 하려면 이 라이브러리 자체를 확장하거나 별도 네이티브 GPIO opcode가 필요하다(현재 없음, 이번 작업 범위 밖).

관련 파일

  • /Users/ef/crowny-space/서버.한선 (수정, 백업 4종: 서버.한선.bak-허브게이트전-*,
서버.한선.bak-확장전-1784265866)
  • /Users/ef/crowny-space/서버.toau (배포됨, 백업 3종 서버.toau.bak-*)
  • /Users/ef/crowny-space/허브/RPi허브.한선 (신규)
  • /Users/ef/crowny-space/허브/RPi허브.toau (신규, 컴파일 산출물)
  • /Users/ef/crowny-space/허브/배포-rpi.md (신규, runbook)
  • /Users/ef/crowny-space/규격/센서코드.한선 (자체시험 가드만 수정, 백업
센서코드.한선.bak-셀프테스트가드전-*, 인코딩/디코딩/체크섬 로직 무변경)
  • /Users/ef/crowny-space/data/허브맵.psv, 명령큐.psv, 시퀀스맵.psv,
수신프레임_1.psv (신규 런타임 데이터)
  • /Users/ef/crowny-space/허브/data/rpi1_seq.txt (신규, 허브 로컬 seq 영속화)

크라우니코드

lookup 시도 2건(허브게이트/SCMD큐) 모두 MISS(신규 도메인) → 직접 생성 → 학습 2건 추가 (crownycode-brain.sh learn "RPi허브에이전트", learn "허브게이트").

잔여 이슈

  • HUB_MODE=gpio 경로 RPi5 실물 미검증(GPIO.한선이 순수 시뮬이라 실물 배선 이슈는
이 코드가 못 잡음).
  • 허브 프로세스 재시작 시 로컬 seq 파일이 유실되면 서버가 일시적으로 "seq 역행"으로
거부(자기치유되지만 완전한 해법은 아님) — 배포-rpi.md §8에 명시.
  • SC1 규격 자체의 RPN(.rpn.한선) 동반은 규격 문서 §10에 이미 "실패 — 후속 작업" 명시된
기존 잔여 이슈(이번 작업 범위 밖, 손대지 않음).
  • 서버 프로세스가 장시간(관측: ~47분) 가동 시 ARRAY 힙(144M cap) OOM으로 크래시하는
현상을 재기동 과정 중 1회 관측(KeepAlive가 자동 재기동해 자기치유). 이번 작업이 기여한 정적 큐브 증가분(+12085)은 확인·완화했으나, 이 ARRAY 힙 문제 자체는 append-log PSV를 매 요청마다 전체 재파싱하는 서버 전체의 기존 아키텍처 특성으로 보이며(내 새 코드만의 문제가 아님), 이번 작업 범위를 넘는 더 큰 리팩터가 필요 — crownystate/관제로 모니터링 권장, 후속 작업 후보로 남김.