npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

homebridge-smartthings-km81

v1.5.8

Published

Unified Homebridge plugin for Samsung devices via SmartThings (legacy AC over TLSv1, modern AC, washer/dryer with notification sensors).

Readme

homebridge-smartthings-km81

Samsung 가전 3종(구형 에어컨 / 신형 에어컨 / 세탁기·건조기)을 하나의 Homebridge 플러그인으로 통합한 플랫폼입니다.

기존에 분리되어 있던 다음 3개 플러그인을 통합·대체합니다.

  • homebridge-samsung-ac (구형 에어컨, TLSv1 직접 통신)
  • homebridge-smartthings-ac-km81 (신형 에어컨, SmartThings API)
  • homebridge-smartthings-washer (세탁기/건조기, SmartThings API)

주요 기능

  • 한 플러그인, 하나의 SmartThings OAuth 토큰(smartthings_km81_token.json)으로 신형 AC + 세탁기 + 건조기를 모두 관리
  • 구형 에어컨은 TLSv1 / SECLEVEL=0 직접 통신을 그대로 유지 (Homebridge 2.0 호환)
  • 신형 에어컨 무풍/자동건조 매핑, 별도 스위치 노출 등 기존 기능 보존
  • 세탁기/건조기 Valve 서비스(Active/InUse/RemainingDuration)는 그대로
  • NEW (v1.2.0): 구형 에어컨 HomeKit↔모드 매핑을 드롭다운 UI로 단순화 (Cool/CoolClean/Dry/DryClean/Wind/Auto + 무풍 옵션), 전원 ON 시 자동 적용
  • NEW (v1.5.0): 세탁기/건조기 종료 알림 센서를 모션 센서로 단순화 — iOS 푸시 1회 + 사용자 지정 이름 지원

설치

npm install -g homebridge-smartthings-km81

Homebridge UI 플러그인 탭에서 검색해 설치할 수도 있습니다.


장치 종류 (deviceType)

devices 배열의 각 항목에 deviceType을 지정합니다. UI에서 선택한 타입에 따라 해당 필드만 표시됩니다.

| deviceType | 설명 | 통신 방식 | | --- | --- | --- | | legacyAc | 구형 Samsung 에어컨 | 로컬 TLSv1 (8888 포트) | | smartAc | 신형 Samsung 에어컨 | SmartThings Cloud | | washer | 세탁기 | SmartThings Cloud | | dryer | 건조기 | SmartThings Cloud |

SmartThings 기반 장치(smartAc / washer / dryer)가 하나라도 있으면 clientId, clientSecret, redirectUri가 필요합니다.


SmartThings OAuth 인증 절차

SmartThings의 보안 정책상 Redirect URI는 https 프로토콜이어야 하며, 별도 포트를 적을 수 없습니다 (즉 기본 443 포트만 허용). 따라서 외부에서 https://<나의도메인> 으로 접속할 수 있는 환경을 만들고, 이를 내부 Homebridge의 http://<homebridge_ip>:8999 로 전달해주는 리버스 프록시(Reverse Proxy) 설정이 필수입니다.

1단계: 리버스 프록시 설정 (HTTPS → 내부 8999)

가장 먼저 외부에서 접속 가능한 https 주소를 준비해야 합니다. Synology NAS의 리버스 프록시, UGreen NAS, Nginx Proxy Manager(NPM), Caddy 등 어떤 도구든 사용 가능합니다.

리버스 프록시 개념

| 구분 | 주소 | 비고 | |---|---|---| | 외부 주소 (SmartThings 등록용) | https://<나의도메인> | 포트 없음 (443 고정) | | 내부 주소 (플러그인이 듣는 곳) | http://<homebridge_ip>:8999 | 포트 8999 고정 |

⚠️ Redirect URI에 https://myhome.com:9001 처럼 포트를 붙이면 SmartThings가 거부합니다. 반드시 https://myhome.com 형태로, 외부에서 443 포트로 접속 가능해야 합니다.

설정 예시 (Nginx Proxy Manager 기준)

  1. NPM 관리 UI → Proxy HostsAdd Proxy Host
  2. Details 탭:
    • Domain Names: myhome.example.com (본인 도메인)
    • Scheme: http
    • Forward Hostname / IP: Homebridge 머신의 내부 IP (예: 192.168.1.10)
    • Forward Port: 8999
    • Block Common Exploits: ✅
    • Websockets Support: ✅ (선택)
  3. SSL 탭:
    • SSL Certificate: Request a new SSL Certificate (Let's Encrypt) 선택
    • Force SSL: ✅
    • HTTP/2 Support: ✅
    • 본인 이메일 입력 후 약관 동의 → Save

설정 예시 (Synology NAS 기준)

  1. 제어판 → 로그인 포털 → 고급 → 리버스 프록시 → 생성
  2. 소스: 프로토콜 HTTPS, 호스트 myhome.example.com, 포트 443
  3. 대상: 프로토콜 HTTP, 호스트 <homebridge_ip>, 포트 8999

사전 체크

  • 라우터에서 외부 443 포트가 NAS의 443 포트로 포워딩되어 있어야 함
  • DDNS가 현재 공인 IP를 가리키고 있어야 함
  • SSL 인증서가 만료되지 않았어야 함 (Let's Encrypt 자동 갱신 권장)

2단계: SmartThings OAuth 앱 생성 (CLI 방식)

2-1. SmartThings CLI 설치

npm install -g @smartthings/cli

2-2. 개인용 액세스 토큰(PAT) 발급

  1. https://account.smartthings.com/tokens 접속
  2. Generate new token 클릭
  3. 모든 권한(scope) 체크 → 생성
  4. 표시되는 토큰 값을 복사 (페이지를 떠나면 다시 못 봅니다)

2-3. CLI 인증

# "YOUR_PAT_TOKEN" 부분을 위에서 복사한 토큰으로 교체
export SMARTTHINGS_TOKEN="YOUR_PAT_TOKEN"

2-4. OAuth-In SmartApp 생성

smartthings apps:create

대화형 프롬프트에 다음과 같이 입력:

| 항목 | 입력값 | |---|---| | What kind of app | OAuth-In App | | Display Name | Homebridge SmartThings KM81 (자유) | | Description | Homebridge SmartThings KM81 (자유) | | Icon Image URL | (엔터로 넘김) | | Target URL | (엔터로 넘김) | | Select Scopes | 스페이스바로 다음 3개 모두 선택 후 엔터:r:devices:*w:devices:*x:devices:* | | Add or edit Redirect URIs | Add Redirect URI 선택 | | Redirect URI | https://myhome.example.com (1단계의 외부 주소, 포트 없이) | | Add or edit Redirect URIs | Finish editing Redirect URIs 선택 | | Choose an action | Finish and create OAuth-In SmartApp 선택 |

생성 완료 후 출력되는 OAuth Client IdOAuth Client Secret 을 반드시 즉시 복사해 저장하세요. 다시 볼 수 없습니다.

3단계: Homebridge 설정에 입력

Homebridge UI 또는 config.json의 플러그인 블록에 다음을 입력:

  • clientId: 위에서 발급받은 OAuth Client Id
  • clientSecret: 위에서 발급받은 OAuth Client Secret
  • redirectUri: 2-4에서 입력한 것과 정확히 동일한 값 (예: https://myhome.example.com)

Homebridge 재시작.

4단계: 권한 허용

  1. Homebridge 로그에 인증 URL이 표시됩니다 (예시):
    인증 URL: https://api.smartthings.com/oauth/authorize?client_id=...&scope=...&redirect_uri=https%3A%2F%2Fmyhome.example.com
  2. 해당 URL을 브라우저로 열어 SmartThings 로그인 → 위치 선택 → 인증 클릭
  3. 자동으로 https://myhome.example.com/?code=... 로 리다이렉트 → 리버스 프록시 통해 내부 8999 포트로 전달 → 플러그인이 토큰을 발급받아 smartthings_km81_token.json에 저장
  4. 로그에 최초 토큰 발급 완료! 메시지 확인
  5. Homebridge를 한 번 더 재시작하면 장치가 추가됩니다.

Webhook lifecycle CONFIRMATION 요청(SmartThings가 처음 앱 등록할 때 보내는 핸드셰이크)도 같은 8999 포트의 서버가 자동 처리합니다.


설정 예시 (config.json)

{
  "platform": "SmartThingsKM81",
  "name": "SmartThings KM81",

  "clientId": "YOUR_CLIENT_ID",
  "clientSecret": "YOUR_CLIENT_SECRET",
  "redirectUri": "https://myhome.example.com",

  "temperatureMin": 18,
  "temperatureMax": 30,
  "temperatureStep": 1,

  "devices": [
    {
      "deviceType": "legacyAc",
      "name": "거실 에어컨",
      "ip": "192.168.1.50",
      "token": "LEGACY_TOKEN",
      "swingModeType": "comfort",
      "pollingInterval": 60,
      "hkCoolMode": "DryClean",
      "hkCoolWithWindFree": true,
      "hkHeatMode": "none",
      "hkAutoMode": "none",
      "powerOnMode": "DryClean",
      "powerOnWithWindFree": true
    },
    {
      "deviceType": "smartAc",
      "deviceLabel": "안방 에어컨",
      "coolModeCommand": "dry",
      "swingBinding": "windFree",
      "lockBinding": "autoClean",
      "exposeWindFreeSwitch": true,
      "exposeAutoCleanSwitch": true
    },
    {
      "deviceType": "washer",
      "deviceLabel": "세탁기",
      "model": "WF24B9600",
      "enableNotificationSensor": true,
      "sensorName": "세탁기 종료알림",
      "sensorPollInterval": 30
    },
    {
      "deviceType": "dryer",
      "deviceLabel": "건조기",
      "model": "DV90B6800",
      "enableNotificationSensor": true,
      "sensorName": "건조기 종료알림"
    }
  ]
}

세탁기/건조기 종료 알림 센서

세탁/건조가 끝나는 순간 iOS 푸시 알림 1회를 받기 위한 가상 모션 센서를 별도 액세서리로 노출합니다. HomeKit 자동화 트리거로도 사용 가능합니다.

옵션

| 필드 | 타입 | 기본값 | 설명 | | --- | --- | --- | --- | | enableNotificationSensor | boolean | false | 종료 알림 모션 센서 활성화 | | sensorName | string | "{장치명} 종료알림" | HomeKit에 표시될 모션 센서 이름 | | sensorPollInterval | integer | 30 (최소 5) | 운전 종료 감지용 SmartThings 상태 폴링 주기(초) |

동작

  • 직전 상태가 active였다가 inactive로 바뀌는 순간 모션 센서를 detected로 트리거 → 약 10초 후 자동으로 해제
  • 모션 센서를 선택한 이유: iOS HomeKit의 푸시 알림이 motion=false → true 전환에서만 발생하므로 운전 종료 시 정확히 1회만 알림이 옴 (Contact/Occupancy는 양방향이라 2회 발송됨)
  • 10초 후 자동 해제는 다음 종료 사이클에서 또 알림을 받기 위해 필수
  • 폴링은 enableNotificationSensor: true인 장치에만 시작됨

사용 방법

  1. Homebridge 설정에서 세탁기/건조기 각각 enableNotificationSensor 체크 + (선택) sensorName 입력
  2. Homebridge 재시작 → 모션 센서 액세서리가 자동 생성됨
  3. iOS 홈 앱 → 해당 모션 센서 액세서리 → "센서 활동 알림" 켜기
  4. 운전이 끝나면 폰에 푸시 알림이 1회 도착

HomeKit 자동화 예시

| 시나리오 | 트리거 | 동작 | | --- | --- | --- | | 세탁 완료 시 거실 조명 깜빡임 | "세탁기 종료알림"에서 동작 감지되면 | 거실 조명 On → 1분 후 Off | | 건조 완료 시 가족에게 알림 | "건조기 종료알림"에서 동작 감지되면 | "건조 끝났어요" 메시지 전송 |

v1.5.0 마이그레이션: 이전 버전의 sensorTypes / triggerMode 배열 옵션은 제거되었습니다. config.json에 남아 있어도 무시되며 다음 시작 시 기존 접촉/점유 센서 액세서리는 자동으로 정리됩니다. iOS 홈 앱에서 새로 나타나는 모션 센서에 "활동 알림"을 다시 켜주세요.


구형 에어컨 (legacyAc) 토큰 추출 가이드

legacyAc 장치를 사용하려면 에어컨의 고유 인증 토큰이 필요합니다. 토큰은 DNS 스푸핑(Spoofing) 기법으로, 에어컨이 삼성 클라우드(api.smartthings.com)와 통신하는 내용을 중간에서 가로채어 추출합니다.

⚠️ 사전 준비물

  • Homebridge가 설치된 컴퓨터(NAS / 라즈베리파이 / Mac 등) — Python 3 + OpenSSL 필요
  • 공유기 관리자 페이지 접근 권한 (정적 DNS 설정 변경용)
  • 에어컨을 Wi-Fi 설정 모드로 다시 연결할 준비

1단계: 가짜 서버 스크립트 준비

아래 Python 코드를 fake_server.py 라는 이름으로 컴퓨터에 저장합니다.

#!/usr/bin/env python3
import ssl
import socket
import os
import threading

LISTEN_IP = '0.0.0.0'
HTTPS_PORT = 443
CERT_FILE = 'temp_server_cert.pem'
KEY_FILE = 'temp_server_key.pem'

def generate_self_signed_cert(cert_file, key_file):
    if not (os.path.exists(cert_file) and os.path.exists(key_file)):
        print(f"임시 서버 인증서 '{cert_file}' 및 '{key_file}' 생성 중...")
        subj = "/CN=api.smartthings.com"
        os.system(f'openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout {key_file} -out {cert_file} -subj "{subj}"')
    print("임시 서버 인증서 준비 완료.")

def handle_client(conn, addr):
    print(f"\n>>> [연결 수립] From: {addr}")
    try:
        while True:
            data = conn.recv(8192)
            if not data:
                break
            decoded_data = data.decode('utf-8', errors='ignore')
            print("\n" + "="*20 + " 데이터 수신 " + "="*20)
            print(decoded_data)
            for line in decoded_data.splitlines():
                if 'authorization' in line.lower():
                    print("\n" + "*"*20 + " 토큰 발견 " + "*"*20)
                    token = line.split(' ')[-1]
                    print(f"추출된 토큰: {token}")
                    print("*"*56)
                    print("이 토큰을 복사하여 Homebridge 설정에 사용하세요.")
            conn.sendall(b'HTTP/1.1 200 OK\r\n\r\n')
    except Exception as e:
        print(f"[오류] 클라이언트 처리 중 오류: {e}")
    finally:
        print(f"<<< [연결 종료] From: {addr}")
        conn.close()

def main():
    generate_self_signed_cert(CERT_FILE, KEY_FILE)
    context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    context.load_cert_chain(certfile=CERT_FILE, keyfile=KEY_FILE)
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.bind((LISTEN_IP, HTTPS_PORT))
        sock.listen(5)
        print("\n" + "="*50)
        print(f"가짜 삼성 클라우드 서버가 시작되었습니다. (포트: {HTTPS_PORT})")
        print("이제 에어컨을 Wi-Fi 설정 모드로 변경하고, SmartThings 앱으로 연결을 시도하세요.")
        print("="*50)
        while True:
            conn, addr = sock.accept()
            threading.Thread(target=handle_client, args=(conn, addr)).start()

if __name__ == '__main__':
    try:
        main()
    except PermissionError:
        print("\n[오류] 443 포트를 사용하려면 root 권한이 필요합니다. 'sudo python3 fake_server.py'로 실행해주세요.")
    except KeyboardInterrupt:
        print("\n서버를 종료합니다.")
    finally:
        if os.path.exists(CERT_FILE): os.remove(CERT_FILE)
        if os.path.exists(KEY_FILE): os.remove(KEY_FILE)

2단계: DNS 스푸핑 설정 (가장 중요)

  1. fake_server.py를 실행할 컴퓨터의 내부 IP 주소를 확인합니다 (예: 192.168.1.10).
  2. 공유기 관리자 페이지(보통 192.168.0.1 또는 192.168.1.1)에 접속.
  3. '정적 DNS', 'DNS 호스트 이름' 같은 메뉴 찾기 (공유기마다 명칭이 다름).
  4. 아래 항목으로 정적 DNS 규칙 추가:
    • 호스트 이름: api.smartthings.com
    • IP 주소: 위 1번에서 확인한 컴퓨터 IP (예: 192.168.1.10)

이렇게 하면 에어컨이 api.smartthings.com을 우리 컴퓨터로 인식합니다.

3단계: 토큰 추출 실행

  1. 터미널에서 root 권한으로 가짜 서버 실행 (443 포트 필요):
    sudo python3 fake_server.py
  2. 에어컨을 Wi-Fi 설정 모드로 변경 → SmartThings 앱에서 네트워크 연결 절차 진행.
  3. 에어컨이 Wi-Fi에 연결되면 우리 PC의 가짜 서버로 접속을 시도. 터미널에 다음과 같이 출력됩니다:
    ******************** 토큰 발견 ********************
    추출된 토큰: 8G7s7VTGGG
    ********************************************************
  4. 이 토큰을 Homebridge UI에서 legacyAc 장치의 인증 토큰 필드에 입력합니다.

4단계: DNS 설정 원복 (필수)

토큰을 얻었으면 반드시 2단계에서 추가한 정적 DNS 규칙을 삭제해야 합니다. 그렇지 않으면 인터넷 사용에 문제가 생기거나 에어컨이 계속 가짜 서버로 접속하게 됩니다.

🔒 보안 경고: 이 통신은 오래된 TLSv1을 사용하므로 신뢰할 수 있는 로컬 네트워크에서만 사용하세요.


HomeKit ↔ 구형 AC 모드 매핑 (legacyAc, v1.2.0+)

구형 삼성 에어컨은 단순 Cool/Dry/Auto/Wind 외에도 CoolClean(냉방청정), DryClean(제습청정) 같은 복합 모드를 지원합니다. HomeKit의 냉방(Cool) / 난방(Heat) / 자동(Auto) 각 버튼을 어떤 실제 AC 모드에 매핑할지 드롭다운으로 선택할 수 있습니다.

설정 필드 (legacyAc 장치 단위)

| 필드 | 설명 | 기본값 | |---|---|---| | hkCoolMode | HomeKit '냉방' 버튼이 보낼 AC 모드 (enum) | "Cool" | | hkCoolWithWindFree | HomeKit 냉방 시 무풍(Comode_Nano) 같이 켜기 | false | | hkHeatMode | HomeKit '난방' 버튼이 보낼 AC 모드 (enum) | "none" (숨김) | | hkHeatWithWindFree | HomeKit 난방 시 무풍 같이 켜기 | false | | hkAutoMode | HomeKit '자동' 버튼이 보낼 AC 모드 (enum) | "none" (숨김) | | hkAutoWithWindFree | HomeKit 자동 시 무풍 같이 켜기 | false | | powerOnMode | 전원 ON 시 자동 적용할 AC 모드 (enum) | "none" (직전 모드 유지) | | powerOnWithWindFree | 전원 ON 시 무풍 같이 켜기 | false |

선택 가능한 모드 (enum 값)

| 값 | 의미 | |---|---| | none | 사용 안 함 (HomeKit 버튼 숨김 / 전원 ON 시 모드 변경 안 함) | | Cool | 냉방 | | CoolClean | 냉방청정 | | Dry | 제습 | | DryClean | 제습청정 | | Wind | 공기청정 (송풍) | | Auto | 스마트 쾌적 |

동작 방식

  • HomeKit에서 모드 버튼을 누르면 PUT /devices/{N}/mode{"modes":["<선택한값>"]} 전송
  • WithWindFree 체크가 켜져 있으면 이어서 {"options":["Comode_Nano"]} 도 전송
  • none 선택 시 해당 HomeKit 버튼이 validValues에서 제외되어 HomeKit에 아예 안 보임
  • 전원 ON 시 powerOnModenone 이 아니면, 전원 명령 직후 자동으로 해당 모드 적용

설정 예시

예시 A — 전원 ON 시 항상 "제습청정 + 무풍"으로 시작, HomeKit은 냉방만 노출

{
  "deviceType": "legacyAc",
  "name": "거실 에어컨",
  "ip": "192.168.1.50",
  "token": "YOUR_TOKEN",

  "hkCoolMode": "DryClean",
  "hkCoolWithWindFree": true,

  "hkHeatMode": "none",
  "hkAutoMode": "none",

  "powerOnMode": "DryClean",
  "powerOnWithWindFree": true
}

예시 B — HomeKit 3개 버튼을 각각 다른 청정 모드로

{
  "deviceType": "legacyAc",
  "name": "안방 에어컨",
  "ip": "192.168.1.51",
  "token": "YOUR_TOKEN",

  "hkCoolMode": "CoolClean",
  "hkHeatMode": "DryClean",
  "hkAutoMode": "Auto",

  "powerOnMode": "CoolClean"
}

💡 HomeKit이 'Heat'를 난방으로 표시하지만, 실제로는 사용자가 원하는 어떤 모드든 매핑할 수 있습니다 (이름표일 뿐).

v1.1.x 에서 v1.2.0 마이그레이션

기존 hkCoolEnabled/hkCoolModes[]/hkCoolOptions[] 같은 배열 기반 필드도 자동으로 인식됩니다 (config.json을 안 고쳐도 v1.2.0 에서 그대로 작동). UI에서 다시 저장하면 새 필드(hkCoolMode, hkCoolWithWindFree)로 정리됩니다.


구형 에어컨 (legacyAc) 참고

  • 인증서 경로(certPath/keyPath)를 비워두면 패키지에 포함된 cert/cert.pem을 사용합니다.
  • swingModeType은 모델에 따라 comfort(무풍) 또는 wind(상하 바람) 중 선택.
  • TLSv1 / DEFAULT@SECLEVEL=0은 구형 펌웨어 호환을 위해 의도적으로 사용합니다.
  • deviceIndex / setDeviceIndex: 하나의 에어컨 본체에 여러 Devices[N] 엔트리가 있는 모델(예: 스탠드+벽걸이 결합)에서 어떤 인덱스를 읽고/쓸지 지정합니다. 기본값 0.

마이그레이션 가이드

기존 3개 플러그인을 사용 중이라면, 본 플러그인 설치 후:

  1. 기존 플러그인의 platform 블록을 config.json에서 제거합니다.
  2. 본 플러그인(SmartThingsKM81) 블록을 추가하고 devices 배열에 항목별 deviceType을 명시합니다.
  3. 기존 토큰 파일(smartthings_ac_token.json, smartthings_washer_token.json)이 있더라도 사용하지 않습니다. 본 플러그인은 새 OAuth 흐름으로 smartthings_km81_token.json을 새로 발급합니다.
  4. Homebridge 재시작 → 인증 URL 접속 → 권한 허용 → 재시작.

라이선스

MIT © Km81