크라우니스페이스 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제거 함정 대응). 서버가
data/수신프레임_N.psv(회전: 3800자 근접 시 다음 N)에 기록. 미등록 엔티티는 자동등록.
응답 {"ok":1,"accepted":N,"rejected":M}.
GET /api/commands?hub=<id>— 허브 소유 엔티티의 미전달 SCMD 프레임 반환(¶ 구분),
data/허브맵.psv(hub|entityId).
POST /api/hub/register—{"hub":"rpi1","entities":"a,b,.."}→ 허브맵 갱신.- 기존
_처리커맨드(POST /api/command)를 확장: 대상 엔티티가 허브 소유면
data/명령큐.psv에 SCMD를 큐잉(체크섬 포함, 규격 그대로).
- 버그 발견·수정:
본문추출()이"\n\n"(LF LF, curl은 절대 보내지 않음) 또는 첫"{"
SC1|...) 본문을 못 읽는 결함을 발견해
"\r\n\r\n"(실제 HTTP 헤더 종결자) 우선 탐색을 추가(기존 JSON 경로는 그대로 보존, 회귀 없음).
- 성능/안정성 이슈 발견·완화: 처음에 규격 정본 코덱(
규격/센서코드.한선, 27타입
가져오기했더니 정적 큐브 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.한선 핀읽기,
규격/센서코드.한선 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 역행 거부"에
- 종료 조건 명시(HUB_CYCLES>0이면 도달 시 종료) — 백그라운드 폭주 금지 가드레일 준수.
허브/배포-rpi.md— RPi5 빌드/배치/systemd 서비스화 runbook(스크립트 아닌 문서).
E2E 실측 결과 (라이브 :9607 대상)
- 허브 등록 → sim HUB_CYCLES=3 →
{"ok":1,"accepted":3,"rejected":0}× 3회(9프레임)
/api/entities에 hub 보고값 반영,
/api/logbook에 cause:"hub" 다수 확인.
- 명령 왕복: POST /api/command(light.veranda, 허브 소유) →
/api/commands?hub=rpi1에
- 체크섬 훼손 프레임 1개 별도 POST →
{"ok":1,"accepted":0,"rejected":1}확인.
- 서버 회귀 8종(health/spaces/entities/logbook/tick/energy/bridge.js/command) 전부
launchctl kickstart -k로 재기동 후 허브맵·명령큐·엔티티 상태 전부 파일 기반이라
무손실 복원(추가 부트스트랩 코드 불필요 — 기존 WAL재생 아키텍처 그대로 적용됨) 확인.
- 실패 없이 완주 — 서버 원상복구 상황 없었음(백업 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으로 크래시하는