toddaustin07/edgebridge 의 포크입니다. 원작 edgebridge 에 AndroidEdgeBridge(AEB) 의 기능 대부분(LLM·Bluetooth 제외)을 이식하고, 라즈베리파이 / 시놀로지 NAS 호환 멀티 아키텍처 Docker 이미지 를 Docker Hub 로 자동 배포합니다.
docker pull woobooung/edgebridge-aeb · 지원 아키텍처: linux/amd64, linux/arm64
- MQTT 브리지 참고 구현 코드를 제공해주신 두더싱(스마트싱스 네이버 카페) 산사나이님께 진심으로 감사드립니다. 이 포크의 MQTT 이식은 산사나이님이 직접 테스트하고 공유해주신 코드를 1차 레퍼런스로 삼았습니다.
- 원본 브리지 서버를 만들어 공개해주신 Todd Austin (toddaustin07) 님께 감사드립니다.
- 두더싱 카페(스마트싱스 네이버 카페, 비공식): https://cafe.naver.com/dothesmartthings
- AndroidEdgeBridge(AEB) 홈페이지: https://aeb.dothesmartthings.com
- AEB 개발자 가이드(이식한 API 원문): https://aeb.dothesmartthings.com/dev-guide.html
- 원작 edgebridge: https://github.com/toddaustin07/edgebridge
| 기능 | 원작 edgebridge | edgebridge-aeb |
|---|---|---|
/api/forward (HTTP 포워딩) |
GET / POST / PUT | + DELETE / PATCH 추가 |
| 한글·멀티바이트 응답 truncation | ❌ 응답이 잘림(버그) | ✅ 수정됨 (아래 설명) |
/mqtt/* MQTT 브리지 (mTLS 구독 → 허브 포워딩) |
없음 | ✅ 이식 (스펙) |
/api/redirect (path→URL 영속 매핑 + 자동 프록시) |
없음 | ✅ 이식 |
/api/callback (name 키로 임의 값 저장/조회) |
없음 | ✅ 이식 |
mDNS 자동 발견 (_edgebridge._tcp) |
없음 | ✅ 이식 (드라이버가 브리지 자동 검색, host 네트워크 필요) |
/api/ping |
단순 200 | ✅ AEB 호환 JSON (battery=100, bridgeVersion, mqtt 세션 요약 등) |
| 데이터 영속화 | .registrations 만 |
.registrations + redirects.jsonl + callbacks.jsonl (data dir) |
| 멀티 아키텍처 Docker 이미지 자동배포 | 수동 빌드 | ✅ GitHub Actions → Docker Hub (amd64/arm64) |
| 동시 요청 처리 | 단일 스레드 | ThreadingHTTPServer (멀티 스레드) |
/api/llm(LLM 직접 호출) — 의도적으로 제외, 호출 시 404.- Bluetooth(BT) 경로 API — 제외.
- AEB ping의
pub_key(Config Sync),supportedAiOptions(LLM), OAuth 토큰 필드 — 미이식 기능이라 ping에서 빈값/false 처리. /api/forward의 ST OAuth access_token 자동 갱신 주입 — 헤드리스 Docker 환경에 부적합하여 제외. 대신 원작과 동일하게 config 의 PAT(SmartThings_Bearer_Token) 를api.smartthings.com요청에 자동 주입.
원작 edgebridge.py 는 응답을 보낼 때 Content-Length: len(문자열) 로 헤더를 설정합니다.
Python len() 은 문자 수를 세지만 실제 전송은 UTF-8 바이트로 이루어집니다.
한글 1자 = UTF-8 3바이트이므로 Content-Length 가 실제보다 짧게 보고되고,
허브 Edge 드라이버의 LuaSocket 클라이언트는 그 길이만큼만 읽고 소켓을 닫아 한글 직후 JSON 이 잘립니다.
(NEIS 한글 응답에서 약 278바이트 손실 실측됨.)
edgebridge-aeb 는 forward 응답을 업스트림 원본 바이트(r.content) 그대로 전달하고
Content-Length 를 바이트 길이로 계산하며, 업스트림 Content-Type 을 그대로 통과시킵니다.
또한 Accept-Encoding 을 제거해 requests 가 gzip 을 투명하게 해제하도록 하여, 압축 응답도 안전하게 처리합니다.
기본은 host 네트워크입니다. (실제 LAN IP 인식 + mDNS 자동 발견 + MQTT/허브 포워딩이 모두 동작 → 포트 매핑 혼란 없음)
docker run -d --name edgebridge-aeb \
--network host \
-v $(pwd)/data:/data \
--restart unless-stopped \
woobooung/edgebridge-aeb:latest- 포트 매핑이 없고 호스트의
Server_Port(기본 8088)로 직접 수신 →http://<host-ip>:8088. - PAT 넣으려면
-e EB_ST_TOKEN=<36자 PAT>추가. - 웹 대시보드:
http://<host-ip>:8088/dashboard
저장소의 docker-compose.yml(host 네트워크) 사용:
docker compose up -d컨테이너는 데이터(
/data)에.registrations,redirects.jsonl,callbacks.jsonl,mqtt_certs/,install_id를 영속 저장합니다. 포트 격리가 필요하면 bridge 네트워크 버전docker-compose.bridge.yml(또는-p 8088:8088)을 쓰세요 — 단 mDNS·자동 IP 인식은 안 됩니다. (🌐 네트워크 모드 참고)
대부분의 시놀로지(Intel/AMD = amd64, 최신 ARM 모델 = arm64)에서 동작합니다. 멀티 아키텍처라 CPU에 맞는 이미지가 자동 선택됩니다.
File Station 에서 아래처럼 만드세요. edgebridge.cfg 는 data 폴더 안 이 아니라 바깥(나란히) 에 둡니다.
/docker/edgebridge-aeb/
├── data/ → 컨테이너 /data 로 마운트 (등록·redirect·callback·인증서 영속 저장)
└── edgebridge.cfg → 컨테이너 /usr/src/app/edgebridge.cfg 로 마운트 (설정 파일)
- 둘은 컨테이너 안에서 서로 다른 경로로 따로 연결되므로 cfg 를 data 안에 넣을 필요가 없습니다.
edgebridge.cfg는 선택입니다. 기본값(포트 8088 · PAT 없음 · mDNS 켜짐)으로 충분하면 cfg 없이data폴더만 연결해도 됩니다. PAT 입력·포트 변경 등이 필요할 때만 만들어 마운트하세요. (내용은 아래 ⚙️ 설정 파일 참고)
- File Station 에서 위 폴더 구조대로
/docker/edgebridge-aeb/data폴더 생성 (cfg 쓸 거면edgebridge.cfg도 그 옆에 준비). - DSM → Container Manager → 레지스트리 탭에서
woobooung/edgebridge-aeb검색 → 다운로드 → 태그latest선택. - 이미지 탭 → 받은 이미지 선택 → 실행.
- 컨테이너 설정: 이름
edgebridge-aeb, 자동 재시작 활성화 체크. - 네트워크 단계 → "Docker 호스트와 동일한 네트워크 사용" 선택 ← 이게 핵심(host). 포트 설정은 안 합니다. (호스트의 8088 로 직접 수신)
- 볼륨(스토리지) → 폴더 추가:
/docker/edgebridge-aeb/data→ 마운트 경로/data- PAT 등 설정은 환경 변수(
EB_ST_TOKEN)나 cfg 마운트로 — 아래 🔑 PAT 등 설정 적용하기 참고.
- PAT 등 설정은 환경 변수(
- 적용 → 완료 → 실행 →
http://<NAS-IP>:8088접속.
왜 host 인가: 클라이언트 실제 IP 인식 + mDNS 자동 발견 + MQTT/허브 포워딩이 모두 동작하고, 컨테이너-포트 vs 로컬-포트 혼란이 없습니다. 8088 이 NAS 에서 충돌하면 환경 변수
EB_SERVER_PORT로 바꾸세요.포트 격리가 꼭 필요하면(bridge): 네트워크를 bridge 로 두고 포트 설정에서
로컬(원하는값) : 컨테이너 8088(고정)매핑 — 단 mDNS·자동 IP 인식은 안 됩니다.
- File Station 에서 폴더 생성 후
docker-compose.yml업로드. - Container Manager → 프로젝트 → 생성 → 경로를 그 폴더로 지정 → 기존
docker-compose.yml사용 → 빌드/실행.
SmartThings PAT 주입·포트 변경 같은 설정이 필요할 때, 두 방법 중 하나를 쓰면 됩니다.
컨테이너 생성/수정 시 환경(Environment) 탭에 변수만 추가하면 끝 (파일·마운트 불필요):
EB_ST_TOKEN=<36자 PAT>← PAT 자동 주입- 그 외
EB_SERVER_PORT,EB_FW_TIMEOUT등은 환경 변수 표 참고 docker run이면-e EB_ST_TOKEN=<PAT>
-
cfg 파일 만들기 — File Station 엔 텍스트 생성 기능이 없으니, PC 메모장으로 작성해 업로드합니다. 메모장에 아래를 넣고
edgebridge.cfg로 저장:[config] Server_Port = 8088 SmartThings_Bearer_Token = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
→
/docker/edgebridge-aeb/edgebridge.cfg로 업로드 (data폴더와 나란히).⚠️ 토큰은 따옴표 없이 붙여넣으세요."..."로 감싸면 36자를 초과해 무시됩니다.⚠️ "파일 추가" 마운트는 이미 존재하는 파일만 고를 수 있어 먼저 만들어둬야 합니다. -
컨테이너 재생성 — 실행 중엔 볼륨 변경이 어려우니 중지 → 삭제 → 다시 생성. (데이터는
/data볼륨에 남아 안전) -
생성 마법사의 스토리지(볼륨) 단계에서 마운트 2개 추가:
종류 NAS 소스 (파일/폴더) 마운트 경로(컨테이너) 폴더 추가 /docker/edgebridge-aeb/data/data파일 추가 /docker/edgebridge-aeb/edgebridge.cfg/usr/src/app/edgebridge.cfg"마운트 경로"(컨테이너 쪽)는 위 값을 직접 타이핑합니다. 특히 cfg 는 반드시
/usr/src/app/edgebridge.cfg. -
포트·자동재시작 설정 후 실행. cfg 를 수정하면 컨테이너를 재시작해야 반영됩니다.
같은 LAN PC에서 ping 을 호출해, 응답 JSON 의 stOauthConnected 가 true 면 PAT 가 유효하게 잡힌 것입니다:
curl -X POST http://<NAS-IP>:<로컬포트>/api/ping
# ... "stOauthConnected": true ... ← PAT 유효 ✅- Container Manager → 컨테이너 → 로그 탭에 아래가 보이면 정상:
Forwarding Bridge Server v... [edgebridge-aeb] > Serving HTTP on <ip>:8088 - 같은 LAN PC에서 (NAS IP 가
192.168.1.10이라고 가정):curl -i http://192.168.1.10:8088/api/ping # 200 OK curl http://192.168.1.10:8088/api/redirect # [] (빈 목록이 정상)
Raspberry Pi OS 64-bit 권장 (Pi 3 / 4 / 5 / Zero 2 W). 공식 이미지는
linux/arm64.
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER # 로그아웃 후 재로그인하면 sudo 없이 docker 사용mkdir -p ~/edgebridge-aeb/data && cd ~/edgebridge-aeb
docker run -d --name edgebridge-aeb \
-p 8088:8088 \
-v $(pwd)/data:/data \
--restart unless-stopped \
woobooung/edgebridge-aeb:latestdocker logs edgebridge-aeb # 'Serving HTTP on ...:8088' 확인
curl -i http://localhost:8088/api/ping
docker ps # STATUS 가 Up 이면 정상, 부팅 시 자동 시작됨docker pull woobooung/edgebridge-aeb:latest # 최신으로 갱신
docker rm -f edgebridge-aeb && (위 2) 재실행) # 새 이미지로 재기동
docker stop edgebridge-aeb # 중지32비트(armv7) Pi (Pi 1 / 2 / Zero / Zero W) 는 공식 이미지에 없습니다. 64-bit OS 로 재설치하거나, 소스에서 직접 빌드하세요 (
git clone후docker build -t edgebridge-aeb .; cryptography 컴파일에build-essential libffi-dev cargo필요). 또는 아래 venv 직접 실행 방식을 쓰면 piwheels 가 cryptography 휠을 제공하므로 32비트에서도 동작합니다.
드라이버가 호출하는 기준 주소는 http://<브리지-IP>:8088 입니다. 예 (NAS/Pi IP = 192.168.1.10):
GET http://192.168.1.10:8088/api/forward?url=https://api.smartthings.com/v1/devices
SmartThings API 호출 시 토큰을 자동 주입하려면 edgebridge.cfg 의 SmartThings_Bearer_Token 에 36자 PAT 를 넣으세요.
MQTT 브리지 연동은 참고 드라이버 WooBooung/EdgeBridgeBaseDriver 의 /mqtt/* 흐름을 보세요.
이 이미지는 host 네트워크가 기본입니다. 브리지의 일부 기능은 "나에게 연락한 상대(허브)의 진짜 LAN IP" 를 알아야 하기 때문입니다:
- device→hub 포워딩, MQTT 메시지 허브 전달, mDNS 자동 발견(
_edgebridge._tcp).
Docker bridge 네트워크로 띄우면 들어오는 요청의 출발지가 도커 게이트웨이(172.17.0.1)로 보여 위 기능들이 동작하지 않습니다.
(반면 /api/forward 같은 요청·응답형 기능은 영향 없음.) 그래서 host 를 기본으로 합니다.
docker run -d --name edgebridge-aeb \
--network host \
-v $(pwd)/data:/data \
--restart unless-stopped \
woobooung/edgebridge-aeb:latest- 포트 매핑(
-p)이 없습니다. 호스트의Server_Port(기본 8088)로 직접 수신 →http://<호스트-IP>:8088. - 8088 충돌 시 환경 변수
EB_SERVER_PORT(또는 cfgServer_Port)로 변경. - compose: 기본
docker-compose.yml이 곧 host 입니다 →docker compose up -d. - 시놀로지 GUI: 위 설치 순서 5번에서 "Docker 호스트와 동일한 네트워크 사용" 선택.
- compose
docker-compose.bridge.yml, 또는docker run ... -p <로컬포트>:8088. ⚠️ 이 모드에선 클라이언트 IP가172.17.0.1로 보여 mDNS·device→hub·MQTT 자동 IP 가 동작하지 않습니다. forward 등록 시 주소를 직접 명시해야 합니다.
host(또는 macvlan) 네트워크에서 브리지는 _edgebridge._tcp 서비스로 자신을 광고합니다
(instance EdgeBridge-aeb, TXT install_id/version). EdgeBridgeBaseDriver
등 mDNS 발견을 지원하는 드라이버가 브리지 IP/포트를 자동으로 잡습니다 — 드라이버에 주소를 수동 입력할 필요가 없습니다.
- 끄려면
edgebridge.cfg의mDNS_enabled = no, 이름은mDNS_name으로 변경. ⚠️ bridge 네트워크에선 mDNS 멀티캐스트가 LAN 으로 안 나가서 동작하지 않습니다 (서버는 정상, 발견만 안 됨).
대안: 분리망이거나 host 모드를 못 쓰면 macvlan 으로 브리지에 자체 LAN IP 를 부여하는 방법도 있습니다 (Docker macvlan 네트워크를 직접 구성).
브리지와 같은 포트에서 GET /dashboard 로 간단한 운영 대시보드를 제공합니다.
- 상태 요약: 브리지 버전, 시작 시간, SmartThings PAT 설정/검증 상태, mDNS 상태
- 목록 확인: MQTT 세션, 등록된 디바이스 포워딩, redirect, callback
- 관리 작업: redirect 추가/삭제, callback 저장/삭제,
SmartThings PAT/forwarding_timeout/mDNS_enabled/mDNS_name변경 - JSON 요약 API:
GET /api/dashboard
GET|POST /api/ping 은 AEB 와 동일한 형태의 JSON 을 반환합니다 (기존 200 체크 모니터와도 호환):
- PAT 유효성:
edgebridge.cfg에SmartThings_Bearer_Token이 설정돼 있으면, 브리지가 SmartThings API (GET /v1/locations)를 호출해 토큰이 유효한지 확인합니다. 401 이 아니면 유효로 보고stOauthConnected/stTokenValid를true로 표시합니다. (매 ping 마다 호출하지 않도록 5분간 캐시. PAT 미설정 시 모두false.)
- forward 타임아웃 기본 5초 — 느린 외부 API 는 502 가 날 수 있습니다.
edgebridge.cfg의forwarding_timeout을 늘리세요. - 네트워크 모드 — 위 "🌐 네트워크 모드" 참고. MQTT/허브 포워딩/mDNS 를 쓰면 host 네트워크 권장.
Docker 를 쓰지 않고 Python 으로 바로 돌리는 방법입니다. (가이드 제공: 두더싱 카페 산사나이님) 전제: 시놀로지 패키지 센터 등에서 Python 3 가 설치되어 있어야 합니다 (산사나이님 가이드는 3.14 기준, 3.8+ 면 동작).
# 1) 스크립트가 있는 폴더로 이동 (경로는 본인 환경에 맞게)
cd /volume1/homes/aeb/aeb-bridge
# 2) 가상환경 생성 + 활성화 (프롬프트 앞에 (venv) 가 보이면 성공)
python3 -m venv venv
source venv/bin/activate
# 3) 필수 패키지 설치
pip install paho-mqtt requests cryptography
# (또는) pip install -r requirements.txtpip 자체가 없다면:
wget https://bootstrap.pypa.io/get-pip.py
python3 get-pip.py# 실행 (로그 안 남김)
nohup python3 edgebridge.py > /dev/null 2>&1 &
# 실행 (로그 남김)
nohup python3 edgebridge.py > edgebridge.log 2>&1 &
# 종료
pkill -f edgebridge.py
# 상태 확인
ps -ef | grep edgebridge.py데이터 파일(
.registrations,redirects.jsonl,callbacks.jsonl,mqtt_certs/)은 기본적으로 실행 폴더(또는edgebridge.cfg의Data_Dir/ 환경변수EB_DATA_DIR)에 저장됩니다. 부팅 시 자동 실행이 필요하면 원작 README 의 systemd 가이드를 참고하세요.
기준 주소는 http://<bridge-ip>:8088 입니다. (아래 예시는 192.168.1.88)
GET|POST|PUT|DELETE|PATCH http://192.168.1.88:8088/api/forward?url=<URL 문자열>
api.smartthings.com대상이고 호출자가Authorization을 안 보냈으면 config 의 PAT 를 자동 주입.- 응답은 업스트림 바이트/Content-Type 그대로 전달 (한글 안전).
POST /api/redirect?path=/tesla&target=https://owner-api.teslamotors.com/api
DELETE /api/redirect?path=/tesla
GET /api/redirect # 등록 목록(JSON)
- 등록 후 브리지로 들어온
/tesla/...요청은target + 나머지경로 + 쿼리로 302 리다이렉트됩니다. - 매칭은 대소문자 무시 + 최장 prefix 우선.
POST /api/callback?name=mytoken # 본문(plain text, 최대 64KB)을 저장
DELETE /api/callback?name=mytoken
GET /api/callback # 전체 목록(JSON)
GET /api/callback/mytoken # 단건 값(plain text), 없으면 404
name은[A-Za-z0-9_-]+만 허용. OAuth 콜백 등 비동기 결과를 드라이버가 폴링하는 용도.
외부 MQTT 브로커에 mTLS 로 구독(수신 전용) 하고, 받은 메시지를 허브 Edge 드라이버로 HTTP 포워딩합니다. 전체 계약은 mqtt-bridge-spec-v0.3.md 참고.
| Method | Path | 역할 |
|---|---|---|
| POST | /mqtt/sessions |
세션 + RSA2048 키쌍 + CSR(PEM) 생성 (개인키는 절대 반환 안 함) |
| POST | /mqtt/sessions/{id}/connect |
mTLS 연결 + 토픽 구독 |
| PUT | /mqtt/sessions/{id}/forward |
허브 포워딩 타깃 등록(멱등) |
| GET | /mqtt/sessions/{id}/status |
상태/진단 조회 |
| GET | /mqtt/sessions/{id}/messages?since= |
버퍼된 메시지 폴링(링버퍼 200) |
| DELETE | /mqtt/sessions/{id} |
세션 종료 + 키/인증서 삭제 |
참고 Edge 드라이버: WooBooung/EdgeBridgeBaseDriver
cfg 는 선택입니다. 안 만들면 아래 기본값으로 동작합니다 (포트 8088 · PAT 없음 · mDNS 켜짐).
PAT 입력·포트 변경 등이 필요할 때만 만들어서 컨테이너의 /usr/src/app/edgebridge.cfg 로 마운트하세요.
(Docker 에서의 폴더 배치는 위 📁 폴더 구조 참고 — data 폴더와 나란히 둡니다.)
[config]
Server_IP = # 비우면 자동 감지 (Docker 에선 비워두세요)
Server_Port = 8088 # 컨테이너 내부 수신 포트
SmartThings_Bearer_Token = # 선택: 36자 PAT, 따옴표 없이! (api.smartthings.com 자동 주입 + ping 유효성)
forwarding_timeout = 5 # 느린 외부 API 면 늘리기
console_output = yes
logfile_output = no
logfile = edgebridge.log
Data_Dir = # 비워두세요. Docker 는 EB_DATA_DIR=/data 를 자동 우선 사용
mDNS_enabled = yes # 기본 켜짐. 끄려면 no (host 네트워크에서만 실제 동작)
mDNS_name = EdgeBridge-aeb # 드라이버가 찾는 광고 이름 (그대로 두면 됨)Data_Dir는 비워두세요 — 환경변수EB_DATA_DIR(=/data)가 우선합니다.mDNS_enabled/mDNS_name은 안 적어도 기본 켜짐입니다. 끄거나 이름 바꿀 때만 사용.
시놀로지 Container Manager 등에서는 cfg 파일을 마운트하는 대신 "환경 변수" 로 넣는 게 훨씬 간단합니다. 환경 변수가 cfg 보다 우선 적용됩니다.
| 환경 변수 | 역할 | 예시 |
|---|---|---|
EB_ST_TOKEN |
SmartThings PAT(36자) — api.smartthings.com 자동 주입 + ping 유효성 |
xxxxxxxx-xxxx-... |
EB_SERVER_PORT |
컨테이너 내부 수신 포트 (기본 8088) | 8088 |
EB_SERVER_IP |
바인딩 IP (보통 비움) | |
EB_FW_TIMEOUT |
forward 타임아웃(초) | 15 |
EB_MDNS_ENABLED |
mDNS 끄기 | no |
EB_MDNS_NAME |
mDNS 광고 이름 | EdgeBridge-aeb |
EB_DATA_DIR |
데이터 경로 (Docker 기본 /data) |
/data |
예: PAT만 넣고 싶다 → Container Manager 환경 탭에
EB_ST_TOKEN=<36자 PAT>한 줄만 추가하면 끝. cfg 파일도, 볼륨 마운트도 필요 없습니다. (docker run이면-e EB_ST_TOKEN=<PAT>)
이 포크는 main 브랜치에 push 하면 GitHub Actions 가 멀티 아키텍처 이미지를 빌드해 Docker Hub 로 자동 배포합니다
(.github/workflows/docker-publish.yml).
- https://hub.docker.com 가입 후, 리포지토리
edgebridge-aeb생성 (push 시 자동 생성도 됨). - Account Settings → Security → New Access Token 에서 Read/Write 토큰 발급.
- GitHub 저장소 → Settings → Secrets and variables → Actions 에 등록:
DOCKERHUB_USERNAME= Docker Hub 사용자명 (예:woobooung)DOCKERHUB_TOKEN= 위에서 발급한 액세스 토큰
main에 commit & push → Actions 탭에서 빌드 확인.- 버전 릴리스는
git tag v1.0.0 && git push --tags→:1.0.0,:1.0,:latest태그가 함께 발행됩니다.
docker buildx imagetools inspect woobooung/edgebridge-aeb:latest
# linux/amd64, linux/arm64 매니페스트가 보이면 정상원작 edgebridge 의 사용 사례, 동반 Edge 드라이버 목록, systemd 자동 실행, 모니터링 드라이버 등 일반적인 사용법은 원작 README 를 참고하세요: https://github.com/toddaustin07/edgebridge#readme
원작과 동일하게 Apache License 2.0 을 따릅니다. © Todd Austin / contributors.
{ "battery": 100, // 서버는 항상 전원 연결 → 100 고정 "bridgeDevice": "server", "bridgeVersion": "1.0.0_AEB", "serverStartTime": "06/23 14:30", "supportedAiOptions": [], // LLM 미이식 "stOauthConnected": true, // cfg 의 PAT 가 유효하면 true (아래 설명) "stTokenConfigured": true, // PAT 가 cfg 에 설정되어 있는지 "stTokenValid": true, // 그 PAT 가 SmartThings 에서 유효한지 "mqtt": { "total": 1, "connected": 1, "sessions": [ {"id":"sess_...","state":"CONNECTED","lastError":null} ] }, "blocked": { "hosts": 0, "attempts": 0 } }