Releases: Protomothis/smartthings-pc-control
Release list
v1.1.2
[v1.1.2] - 2026-09-28
데스크톱 앱
- 로그인 창이 5초마다 겹쳐 뜨던 문제를 고쳤습니다. 시크릿을 저장한 뒤 뜨는 로그인 창에 입력하던 글자가 지워지고, 몇 번 누른 끝에야 "Invalid secret" 뒤에 접속되던 현상입니다. 연결되지 않은 동안 5초마다 도는 재연결이 401을 받을 때마다 새 로그인 창을 위에 띄워 빈 입력칸이 포커스를 가져갔고, 쌓인 창들이 틀린 시크릿을 보내 5회 실패 잠금(60초)에 걸리게 했습니다. 이제 로그인 창은 한 번에 하나만 뜨고, 창이 떠 있거나 로그인 중에는 재연결이 쉬며, 빈 시크릿은 보내지 않습니다 ([로그인] 버튼이 입력 전까지 꺼져 있고 Enter로도 보낼 수 있습니다). [취소]하면 다시 묻지 않고 상단 줄에
로그인이 필요합니다와 [로그인] 버튼을 남깁니다 (#98) - 설정 탭에서 시크릿을 바꿔 저장하면 앱이 새 시크릿으로 바로 다시 로그인합니다. 실패할 때만 로그인 창을 띄웁니다 (#98)
- 로그인 실패 문구를 나눴습니다 — 틀린 시크릿은
시크릿이 올바르지 않습니다.(창이 다시 열림), 잠금에 걸리면로그인 시도가 너무 많습니다. 60초 후 다시 시도하세요.(상단 [로그인]으로 다시 시도). 서비스의 잠금 기준(5회 실패 · 60초)은 그대로입니다 (#98) - 원격 명령 유예 길이는 지금처럼 설정 탭의 원격 명령 유예 드롭다운(사용 안 함 · 10초~30분, 기본 5분)에서 바꿉니다. 동작은 바뀌지 않았고, 이 위치를 Wiki 원격 명령 유예와 예약에도 적었습니다 (#98)
Full Changelog: v1.1.1...v1.1.2
Edge driver edge-v1.0.1
- 장치 아이콘을 바꿀 수 있습니다. 환경설정에
아이콘이 생겼습니다 — 기타(기본) · 모니터 · 스위치 · 플러그 · TV · 프로젝터 · 네트워크 · 허브 · 홈시어터 · 리모컨. 앱은 아이콘을 장치의 카테고리로 정하는데 기본 카테고리인기타는 앱에서 아이콘을 고를 수 없어서, 값마다 카테고리만 다른 프로필(pc-monitor.v1등)을 두고 설정을 바꾸면 드라이버가 장치를 그 프로필로 옮깁니다. 화면·설정·자동화는 그대로이고 장치를 다시 추가할 필요가 없으며, 옮긴 직후 비는 줄은 드라이버가 곧 다시 채웁니다 (#100) - 대시보드 타일이 전원 상태를
절전 (Sleeping)·종료 대기 (Shutting down)처럼 문구로 보여 주도록, 타일 문구를 상세 화면의 전원 상태 줄과 같은 일곱 값으로 고정했습니다. 토글은 그대로 스위치입니다. 기존 장치의 타일에 실제로 뜨는지는 Dev 채널 실측 대기입니다 (#101) - 상태 줄이 연결된 PC의 가동 시간을
연결됨 · 3일 2시간처럼, 응답하지 않는 PC가 마지막으로 응답한 때를응답 없음 · 마지막 확인 12분 전처럼 보여 줍니다. 마지막 확인 시각은 허브가 다시 시작해도 남습니다. 한 번도 응답받지 못한 PC와 시크릿·버전 불일치는 예전 문구 그대로이고, 줄이 24자를 넘으면 WoL 꺼짐 안내가 가동 시간보다 먼저입니다 (#102)
채널: Protomothis — 설치 방법은 edge/README.md
v1.1.1
[v1.1.1] - 2026-09-26
장치를 추가하는 길은 SSDP 검색 하나뿐인데, 검색이 이 PC까지 왔는지 확인할 방법이 없었습니다. 이제 앱이 그것을 보여 주고, 검색을 끄는 설정은 사라졌습니다 (#95).
꺼진 PC를 깨울 MAC도 마찬가지로 짐작에 맡겨져 있었습니다. 이더넷·Wi-Fi·가상 어댑터가 섞인 PC에서 드라이버가 "WoL 켜진 첫 어댑터"를 고르면 엉뚱한 MAC이 나옵니다. 이제 PC가 직접 고르고 앱에서 바꿀 수 있습니다 (#96).
서비스
- SSDP 검색을 항상 켭니다.
smartthings.discovery설정을 없앴습니다. 응답기는 서비스가 도는 동안 계속 켜져 있고, 인바운드 UDP 1900 규칙 SmartThings PC Control SSDP는 조건 없이 시작할 때마다 확인·복구합니다./st/v1/*접근 제어는 지금처럼 시크릿과smartthings.allowed_hubs가 맡습니다 (#95) - 옛
config.json의discovery: false는 오류 없이 읽고 무시하며, 다음 저장에서 키를 지웁니다. 그때 로그에SSDP 검색은 항상 켜져 있습니다 (discovery 설정은 더 이상 쓰지 않습니다)를 한 번 남깁니다 (#95) - 이 PC가 응답한 마지막 M-SEARCH의 출처 IP와 시각을 기억합니다 (#95)
GET /api/st/hub에machine_id(전체 값)와ssdp: {running, firewall_rule, last_search: {ip, at}}를 더했습니다. 기존 필드는 그대로입니다 (#95)- WoL 어댑터를 서비스가 고릅니다.
/st/v1/status의wol에selected: {name, mac, ip, wol_enabled, wol_capable, source}가 생겼고,adapters[]에는ip(첫 IPv4)와selected가 붙었습니다.wol.ready도 이제 선택된 어댑터 기준입니다. 기존 필드는 그대로입니다 (#96) - 자동 선택 순서 — ① 허브의
/st/v1요청이 실제로 들어온 인터페이스를 가진 어댑터(연결의 로컬 주소를 매 요청 기억해 어댑터의 IPv4와 대조) → ②wol_enabled→ ③wol_capable→ ④ MAC이 있는 첫 어댑터. ②~④에서는 가상 어댑터(vEthernet· Hyper-V · VirtualBox · VMware · TAP · Tailscale · WireGuard · 루프백 · 블루투스)를 실제 랜카드 뒤로 미루고, 실제 어댑터가 없을 때만 고릅니다 (#96) - 새 설정
smartthings.wol_mac(기본""= 자동).B4-2E-99-45-B4-F5·b4:2e:99:45:b4:f5·b42e9945b4f5를 모두 받아 대문자 하이픈 형태로 저장합니다. 어느 어댑터와도 맞지 않으면 자동으로 되돌리고 로그에 한 번 남깁니다. 다른smartthings키처럼 저장 즉시 반영되며 재시작이 필요 없습니다 (#96) GET /api/st/hub에wol: {selected, auto, adapters}를 더했습니다.auto는 수동 지정 중에도 "자동이면 무엇이 뽑히는가"를 알려 주므로 앱의 드롭다운 첫 항목이 이것을 씁니다 (#96)
데스크톱 앱
- 네트워크 탭의 SmartThings 섹션에 이 PC의 ID(8자리 축약 + [복사]로 전체 값)를 표시합니다. SmartThings 앱의 장치 정보에 보이는 값과 같으므로 여러 PC를 구분할 때 씁니다 (#95)
- 검색 상태 줄 —
검색 응답기 켜짐 · 방화벽 규칙 OK · 마지막 검색 요청 192.168.1.105, 12초 전. 아직 없으면검색 요청 없음, 소켓을 못 열었으면검색 응답기 꺼짐, 규칙이 없으면방화벽 규칙 없음으로 읽습니다 (#95) - 안내 문구 — "SmartThings 앱에서 [주변 기기 검색]을 누르기 전에 이 PC와 PC Control이 켜져 있어야 합니다." 자동 검색 토글은 없어졌습니다 (#95)
- 같은 섹션에 WoL 어댑터 드롭다운. 첫 항목은
자동 (이더넷 · B4-2E-99-45-B4-F5)처럼 지금 자동으로 뽑히는 어댑터를 같이 보여 주고, 그 아래는이더넷 · B4-2E-99-45-B4-F5 · WoL 켜짐/Wi-Fi · … · WoL 꺼짐/… · WoL 미지원입니다. 고르면wol_mac에 저장하고 자동은 빈 값으로 되돌립니다 (#96) - WoL 안내가 고른 어댑터 이름을 말합니다 — "이더넷에서 WoL이 켜져 있습니다" / "Wi-Fi에서 WoL이 꺼져 있습니다 — 어댑터 전원 관리 설정에서 켜 주세요". 네트워크 탭 맨 위 요약 줄도 같은 어댑터를 따릅니다 (#96)
- WebUI 설정 페이지의 SmartThings 블록에도 같은 드롭다운이 있습니다 (#96)
문서
- README에 검색 전제 조건과 "검색이 안 될 때" 점검 순서(앱 켜짐 → 방화벽 규칙 → 마지막 검색 요청 시각 → 허브 allow list)를 넣고, 설정 표에서
smartthings.discovery를 뺐습니다 (#95) - README에 "WoL 어댑터" 절(자동 선택 4단계와 가상 어댑터 처리, 직접 고르는 법)을 넣고 설정 표에
smartthings.wol_mac을 더했습니다.docs/design/edge-driver.md§3.2에wol.selected와adapters[]의ip·selected, §3.7에wol_mac을 적었습니다 (#96)
Full Changelog: v1.1.0...v1.1.1
Edge driver edge-v1.0.0
첫 공개 버전입니다. 커스텀 capability 여섯 — pcPower(전원 상태) · pcRemote(명령 실행) · pcDefer(예약) · pcUser(세션, 옵트인) · pcInfo(연결·업데이트·WoL·안내) · pcVersion(버전 줄) — 으로 상세 화면을 그리며, 프로필은 pc.v1입니다.
채널(
Protomothis)로 나가는 첫 릴리스입니다. 아래는edge-v1.0.0마일스톤에 쌓인 변경입니다.
- 예약 시간 목록을 고르지 않고 닫을 때 나던 "네트워크 또는 서버 오류"를 고쳤습니다. 목록을 닫을 때 앱이 보내는 현재 값은 프레젠테이션의 정수 변환을 거치지 않고 문자열로 나가는데, 정의는 정수를 요구해 클라우드가 거부하고 있었습니다.
schedule의minutes를 문자열 목록(-10과 프리셋 열여섯)으로 다시 정의했습니다. 화면·프리셋·동작은 그대로입니다 (#91) - 정의가 바뀌었으므로 capability id가
pcDelay→pcDefer(numbersystem53811.pcdefer)가 되었습니다. 공개되는 것은 이 id이므로 이전할 장치는 없습니다 (#91) - 버전 줄이 PC가 꺼져 있어도 마지막으로 확인한 서비스 버전을 그대로 보여 줍니다.
v?는 한 번도 응답받지 못한 PC에만 쓰입니다 (#92) - 장치의 모델이 PC 식별자를 담습니다. 앱의 장치 정보에서
PC Control · 58bff996처럼 보이고, 앞 8자는 Windows 앱이 보여 주는 이 PC의 ID와 같은 값입니다. 장치 이름(DESKTOP-ABC 컴퓨터)은 그대로이며, 기존 장치는 다음 상태 조회에 성공할 때 한 번 갱신됩니다 (#94) - 검색이 아무 PC도 찾지 못하면 이제 아무 장치도 만들지 않습니다. 예전에는
PC Control (set IP in settings)장치가 하나 생겼지만, 그것은 "PC가 꺼져 있다"는 사실을 장치로 남기는 일이었고 다음 검색까지 막았습니다. 장치 추가는 검색이 유일한 경로이므로 검색을 누르기 전에 PC와 PC Control이 켜져 있어야 합니다. 주소를 고정하는PC IP 주소환경설정은 그대로입니다 (#94) - PC가 꺼지거나 켜지는 중에는 명령 목록이
종료 진행 중…·켜는 중…으로 바뀌고, 그동안 들어온 명령은 PC로 보내지 않습니다. 상태 줄에 "종료 진행 중 · 끝난 뒤 다시 시도"가 잠깐 뜨고, 전환이 끝나면 목록이 저절로 다시 열립니다. 새로고침·예약 취소·스위치 켜기(= 유예 취소)는 그대로 통과합니다. 막히는 구간은 PC에 설정된 유예 길이를 그대로 따르므로, 유예를 5분으로 잡아 두었다면 그 5분이 해당합니다. 3일 뒤 종료 같은 긴 예약은 전환이 아니므로 아무것도 막지 않습니다 (#93) - WoL은 이제 PC가 고른 랜카드로 보냅니다. 랜카드가 여럿인 PC(이더넷 + Wi-Fi, Hyper-V·VPN 가상 어댑터)에서 드라이버가 "WoL이 켜진 첫 어댑터"를 골라 엉뚱한 MAC으로 깨우려 하던 것을, 데스크톱 앱 네트워크 탭의 WoL 어댑터 선택을 그대로 따르도록 바꿨습니다.
MAC 주소환경설정을 채워 넣었다면 그 값이 계속 최우선이고, 아직 어댑터를 고르지 않는 옛 서비스에서는 예전 규칙 그대로 동작합니다. "WoL 꺼짐" 안내도 고른 어댑터 하나를 기준으로 하며, 상태 줄과 메시지 줄이연결됨 · WoL 꺼짐 (이더넷)처럼 어느 랜카드를 열어야 하는지 이름을 댑니다 (#97) - 명령 목록이 보여 줄 항목을 새
supportedCommands속성에서 읽도록 했습니다. 전환 중에 항목이 실제로 사라지는지는 실기 확인 대기이고, 먹지 않아도 위의 문구와 드라이버 가드는 그대로 동작합니다 (#93) - 정의가 바뀌었으므로 capability id가
pcExec→pcRemote(numbersystem53811.pcremote)가 되었습니다. 공개되는 것은 이 id이므로 이전할 장치는 없습니다 (#93) - 프로필 이름을
pc.v1로 초기화했습니다. 개발 중 쌓인pc.v2…pc.v17은 어느 사용자의 허브에도 간 적이 없어 패키지에서 뺐습니다. 화면이 바뀌면 다음 버전은pc.v2이고, 기존 장치는 그때부터 첫init에서 자동으로 이전됩니다 (#90)
채널: Protomothis — 설치 방법은 edge/README.md
v1.1.0
[v1.1.0] - 2026-09-22
SmartThings를 위한 전용 Edge 드라이버와, 그 드라이버가 쓰는 서비스 API /st/v1이 추가되었습니다. 설계 문서: docs/design/edge-driver.md.
기존 PCControl 드라이버 호환 경로(/{secret}/{command})는 그대로입니다. 옮겨 갈 의무는 없습니다.
SmartThings Edge 드라이버 (edge/)
Edge 드라이버는 이 릴리스의 레포에 포함되어 있지만 채널 공개는 추가 실기 테스트 뒤에 별도 태그(
edge-v1.0.0)로 진행합니다. 그때까지 SmartThings 연동은 기존 PCControl 드라이버로 그대로 쓸 수 있습니다.
- 허브 안에서 로컬로 도는 Lua 5.3 드라이버. 장치 하나가 PC 하나이며 자식 장치는 만들지 않습니다 (#71 #81)
- 실제 전원 상태 — 켜짐 · 절전 · 최대 절전 · 꺼짐 · 깨우는 중 · 종료 대기. 스위치는 전원 상태에서 파생되므로 실제와 어긋나지 않습니다 (#71 #72)
- 커스텀 capability 여섯 —
pcPower(전원 상태),pcExec(명령 실행과 마지막 실행),pcDelay(예약 표시·취소와 예약할 명령),pcUser(잠금·유휴, 옵트인),pcInfo(연결·업데이트·WoL·안내),pcVersion(버전 줄) (#72 #86) - 상세 화면은 두 카드 — 위에 상태(전원 상태 · 마지막 실행 · 예약 요약 · 세션 · 상태 · 버전), 아래에 조작(명령 · 예약할 명령 · 예약 시간). 모든 줄이 값을 가집니다 (#78 #82 #85 #86)
- 명령 목록에서 깨우기 · 절전 · 최대 절전 · 재시작 · 종료 · 잠금 · 화면 끄기 · 화면 켜기를 실행하고, 유예를 따를지는
버튼 실행 방식환경설정이 정합니다 (#82 #84) - 예약은 명령과 시간을 각각 고르고, 시간 목록의 취소가 예약을 지웁니다. 프리셋은 5 · 10 · 15 · 30 · 45분, 1 · 1.5 · 2 · 3 · 4 · 6 · 8 · 12시간, 1 · 2 · 3일 — 최대 72시간이고 앱 예약 탭 · WebUI · 텔레그램도 같은 상한을 씁니다. 예약 요약은 한 시간부터 "2시간 후", 하루부터 "1일 3시간 후"로 읽습니다. 두 목록 모두 고르지 않고 닫으면 아무 일도 일어나지 않습니다 (#84 #85 #88 #89)
- 버전 줄 — "v1.1.0 · 드라이버 1.0". 장치의 화면은 추가 시점의 정의로 굳으므로, 화면이 바뀔 때마다 프로필 이름 버전이 올라갑니다(현재
pc.v15) (#85 #86 #87 #88 #89) - 값 문구는 프레젠테이션에 "켜짐 (On)"처럼 한국어·영어를 병기합니다. 앱이 번역 파일의 속성 값 라벨을 쓰지 않는 것이 확인됐습니다 (#83)
- Wake-on-LAN — 매직 패킷을 즉시 · 2초 뒤 · 5초 뒤, 포트 7과 9로 보내고 90초 안에 응답이 없으면 실패를 알립니다. MAC은 비워 두면 서비스가 보고한 어댑터를 씁니다 (#73)
- SSDP 자동 검색으로 장치를 만들고,
machine_id로 중복을 막고,followDiscovery로 DHCP 주소 변화를 따라갑니다 (#73) - 프레젠테이션이 바뀌면 프로필 이름 버전을 올리고, 기존 장치는 첫
init에서 현재 프로필로 자동 이전됩니다 (#79 #82 #83 #84 #85 #86) - 환경설정 — IP · 검색 따라가기 · 포트 · 시크릿 · MAC · WoL 브로드캐스트 · 상태 확인 주기 · 스위치 끄기 동작 · 버튼 실행 방식 · 문구 언어. 제목과 설명은 한국어에 영어 병기 (#78)
- CI —
edge/**변경마다 Lua 테스트와 문법 검사,edge-vX.Y.Z태그에서src/driver_version.lua와 태그 일치 검증 후 패키징 → 채널 배정 → 릴리스 자산 첨부 (#74) - 배포 도구 — 네임스페이스 일괄 적용
tools/apply-namespace.js, capability 생성tools/create-capabilities.sh, 정의·프레젠테이션·번역 갱신tools/sync-capabilities.sh(#74 #78)
서비스 /st/v1 API (#67)
GET /st/v1/status— 전원 · 유예 · 예약 · 마지막 명령 · 업데이트 · WoL 어댑터 · 디스플레이 · 세션을 한 덩어리로POST /st/v1/command— 명령 + 모드(default/immediate/grace) + 분(0~4320, 0보다 크면 예약) (#89)DELETE /st/v1/schedule— 예약 취소- 헤더 인증 — 시크릿을 URL이 아니라
X-PC-Secret으로 받습니다. 불일치401, 허용 목록 밖403, 초당 10회 초과429 - 예약 출처
smartthings— SmartThings에서 건 예약이 앱 · 트레이 · 텔레그램 어디서나 "SmartThings"로 표시됩니다
푸시 구독 (#68)
POST /st/v1/subscribe로 허브가 콜백을 등록하면 전원 · 예약 · 원격 명령 · 시스템 · 디스플레이 · 세션 이벤트를 즉시 보냅니다. TTL 60~3600초(기본 600), 드라이버는 80%에 갱신합니다- 매 이벤트에 전체 status를 실어 드라이버가 차이를 계산하지 않습니다
power.stopping은 종료 · 재시작 · 절전 · 최대 절전을 구분해 동기로(최대 1.5초) 보냅니다. 그래서 타일이 "꺼짐"이 아니라 "절전"을 표시합니다- 콜백은
http://이고 호스트가 요청 출처 IP와 같은 사설 대역이어야 합니다. 전송 실패가 연속 3회면 구독을 지웁니다 - 알림 카테고리 필터와 조용한 시간대는 장치 상태 푸시에 적용되지 않습니다(알림이 아니라 상태이므로)
SSDP 자동 검색 (#69 #76)
urn:smartthings-pc-control:device:pc:1에 대한 M-SEARCH에 응답하고, M-SEARCH를 받은 인터페이스의 주소로LOCATION을 만듭니다- 무인증
GET /st/v1/description— 프로토콜 · machine_id · 호스트명 · 버전 · 포트 · 시크릿 설정 여부만 반환합니다 - 방화벽 규칙 SmartThings PC Control SSDP(인바운드 UDP 1900)를 설치 시 추가하고,
smartthings.discovery가 켜져 있는 한 서비스 시작마다 확인합니다 (#76)
GUI (#70)
- 네트워크 탭에 SmartThings 섹션 — 연결된 허브(IP · 드라이버 버전 · 마지막 확인), 토글 자동 검색(SSDP) 허용 / 세션 정보 노출(잠금·유휴) / 사용자 이름 포함, 허브 허용 목록과 [현재 허브 추가] · [삭제]
- 시크릿이 비어 있으면 설정을 권하는 안내를 표시합니다
- 새 API —
GET /api/st/hub(연결된 허브 정보),GET /api/telegram/state(폴링 · 409 충돌 상태)
세션 유휴 시간 (#77)
- 트레이 앱이 30초마다
POST /api/session/heartbeat로 유휴 시간을 올리고, 서비스는 90초 이내 값만 상태에 싣습니다. 서비스는 세션 0에 있어 직접 잴 수 없기 때문입니다 - 잠금 여부와 사용자 이름은 트레이 앱과 무관하게 동작합니다. 유휴 변화는 푸시로 보내지 않습니다
텔레그램 (#75)
- 모든 알림과 봇 답장이
🖥 <PC 이름>줄로 시작합니다. 이름은telegram.pc_name, 비어 있으면 호스트 이름 - 여러 PC가 같은 봇 토큰으로
getUpdates를 돌면 텔레그램이 한 쪽만 허용합니다. 이 409 충돌을 감지해 로그와 알림 탭에 경고하고 폴링 백오프를 늘립니다. 방침: 봇 하나 = PC 하나
새 명령
turnscreenon— 꺼진 모니터를 다시 켭니다(로그인 세션 필요)./st/v1/command와 레거시 경로 양쪽에서 쓸 수 있습니다- 텔레그램
/screenon— 같은 명령의 단축키./lock·/screenoff와 함께 확인 없이 실행되는 안전 명령입니다
설정
smartthings.discovery(기본true) — SSDP 응답 on/offsmartthings.allowed_hubs(기본[]) —/st/v1을 쓸 수 있는 허브 IP. 비어 있으면 모두 허용smartthings.expose_session/expose_session_user(기본false) — 잠금·유휴 시간 노출과 사용자 이름 포함telegram.pc_name(기본"") — 메시지 머리말의 PC 이름. 비면 호스트 이름smartthings.*는 모두 핫 리로드입니다(재시작 불필요)
업그레이드 안내
- 기존 설치본은 앱의 [지금 업데이트]로 올리면 됩니다.
config.json은 그대로 호환되고smartthings블록은 기본값으로 채워집니다 - 방화벽 규칙이 하나 늘어납니다 — 자동 검색이 켜져 있으면(기본) 서비스가 시작할 때 인바운드 UDP 1900 규칙을 추가합니다.
install을 다시 돌릴 필요는 없습니다. 원하지 않으면 네트워크 탭에서 자동 검색(SSDP) 허용을 끄세요(이미 만들어진 규칙은uninstall때 삭제됩니다) - 기존 PCControl 드라이버 사용자는 아무것도 하지 않아도 됩니다. 레거시 경로와 응답은 바뀌지 않았고, 두 드라이버를 같은 PC에 동시에 붙여도 서로 방해하지 않습니다
- 새 드라이버를 쓰려면 서비스가 v1.1.0 이상이어야 합니다. 그 아래 버전에 연결하면 드라이버가
버전 불일치로 표시합니다 - 텔레그램을 여러 PC에서 쓰고 있었다면 봇을 PC마다 분리하세요. 같은 토큰을 공유하면 한 PC만 명령을 받습니다
Full Changelog: v1.0.0...v1.1.0
v1.0.0
[v1.0.0]
첫 정식 버전. 텔레그램 알림과 텔레그램에서의 PC 제어가 추가되었습니다. 설계 문서: docs/design/v1.0-notifications.md.
새 기능
- 텔레그램 알림 — 서비스가 이벤트를 텔레그램 봇으로 보냅니다. 카테고리(SmartThings 원격 명령 / 예약 / 전원·서비스 / 보안 / 시스템) 21종을 개별로 켜고 끌 수 있고, 설정은 config.json
telegram·notify에 저장되며 재시작 없이 반영됩니다. Bot API 아웃바운드만 사용해 포트 개방·웹훅이 필요 없습니다 (#55 #56 #60 #63) - 메시지 템플릿 — HTML parse mode, 카테고리 아이콘 + 제목 / 핵심 한 줄 / 필드 / PC 이름·시각 꼬리말 레이아웃. 한국어·영어, 간단/자세히 두 단계. 유예 알림에는 [바로 실행] [취소] 인라인 버튼 (#57)
- 조용한 시간대 — 예: 22:00~07:00(자정 넘김 지원). 걸러진 알림은 해제 시각에 요약 한 통으로 전송, 보안 예외 옵션,
/mute 2h임시 뮤트. 유예 시작·강제 종료 알림은 항상 전송 (#59) - 보안 이벤트 집계 — 잘못된 시크릿 요청과 미허용 채팅 명령은 출처별 첫 건 즉시, 이후 5분 창으로 묶어 건수와 함께 한 번만 알림 (#58)
- 전원·시스템 이벤트 — 서비스 시작(부팅·WoL 복귀, 외부 IP 포함), 절전 해제, 서비스 중지, 버전 변경 감지, 서비스 측 새 릴리스 확인(24시간마다). 릴리스 확인 로직을
internal/release로 분리해 앱과 서비스가 공유 (#60) - 텔레그램에서 PC 제어 — 롱 폴링 인바운드. 허용된 Chat ID만 처리하고 미허용 채팅은 보안 알림으로 보고, 서비스 시작 전에 쌓인 명령은 폐기.
/status/menu/lock/screenoff/sleep/hibernate/restart/shutdown [분]/cancel/now/mute/unmute/help. 전원 명령은 [확인] 버튼 후 즉시 실행, 분을 붙이면 예약(출처telegram). 기본 꺼짐 (#61) - 인라인 키보드와 메시지 편집 — 유예 알림 메시지는 어떤 경로로 끝나든(토스트·트레이·앱·WebUI·API·텔레그램·타이머·대체) 원문 아래 "✅ 취소됨 · 14:32 · 트레이" 같은 결과 줄로 편집되고 버튼이 제거됩니다.
/menu의 확인 흐름은 메뉴 텍스트를 유지하고, 이미 처리된 버튼은 "⏹ 이미 처리됨"으로 정리 (#62) - Bot Token 보호 — Windows DPAPI 머신 범위로 암호화해
dpapi:접두사로 저장. 평문 토큰은 다음 저장 때 자동 암호화./api/config는 마스킹된 값(****1234)과bot_token_set만 노출하며-로 삭제 (#65 #63) - 알림 탭 (데스크톱 앱) — 텔레그램 연결(토큰·Chat ID·[Chat ID 찾기]·[테스트 발송]·봇 상태), 텔레그램에서 제어(허용 Chat ID, 경고), 받을 알림(카테고리 마스터+개별 체크, 모두 켬/끔), 조용한 시간대, 표시(상세 수준·PC 이름). 설정 탭과 같은 변경 감지 저장 (#64)
- 서비스 API —
POST /api/telegram/test,GET /api/telegram/me,GET|POST /api/telegram/chats;/api/schedule출처에telegram추가 (#63 #61) - 오래된 텔레그램 명령 보호 — PC가 꺼져 있거나 절전 중일 때 보낸 명령이 복귀 후 도착하면(10분 초과) 실행하지 않고 "오래된 명령이라 실행하지 않았습니다"를 답장. 서비스 시작 전에 쌓인 명령은 그대로 폐기
- 서명된 업데이트 매니페스트 — 릴리스마다 ed25519로 서명된
update.json(+.sig)을 함께 올리고, 앱은 내장 공개키로 서명을 검증한 뒤에만 매니페스트가 지정한 자산을 받아 SHA-256·크기를 대조하고 실행합니다.version은 릴리스 태그와 일치해야 하며(재생 방지),min_version으로 너무 오래된 설치본의 자동 업데이트를 막을 수 있습니다. 서명이 없거나 검증에 실패한 릴리스는 자동 설치 대신 릴리스 페이지 열기로 폴백. CI에signmanifest sign/verify단계 추가 (#66)
개선 (데스크톱 앱 UX)
- 설정·알림 탭의 [저장]이 스크롤 밖 하단 바에 고정. 변경이 있으면 주황 점이 깜빡이는 "저장되지 않은 변경 사항" 표시와 탭 제목의 "•" 마커가 켜짐
- 변경이 있는 탭에서 다른 탭으로 가거나 창을 닫을 때 [계속 편집] [저장 안 함] [저장] 확인
- 기능 단위 켬/끔(텔레그램 알림·제어, 조용한 시간대, WebUI 접속, 로그인 자동 시작, 업데이트 확인)은 체크박스 대신 토글 스위치
- 다크 테마에서 힌트 문구와 비활성 컨트롤이 읽히도록 회색 톤을 밝게 조정
변경
- 설정 저장이 이제 라이브 설정 위에 덧씌워집니다. 구 버전 앱이나 WebUI가
telegram/notify를 보내지 않아도 값이 지워지지 않습니다 - 서비스 로그의 예약 라인에 출처(origin)가 표기됩니다.
state.json(마지막 실행 버전·알린 릴리스)이 exe 옆에 생성됩니다
업그레이드 안내
- 기존 설치본에서는 앱의 [지금 업데이트]로 교체하거나, 서비스 중지 → exe 교체 → 서비스 시작으로 올리면 됩니다 (재설치 불필요). 기존 config.json은 그대로 호환되며
telegram/notify키는 기본값으로 채워지고, 텔레그램은 설정 전까지 아무 것도 보내지 않습니다 - 텔레그램을 쓰려면 알림 탭에서 봇 토큰과 Chat ID를 넣고 [테스트 발송]으로 확인한 뒤 "텔레그램 알림 사용"을 켜세요
Full Changelog: v0.3.4...v1.0.0
v0.3.4
[v0.3.4]
새 기능
-
원격 전원 명령 유예 시간 선택 — 설정 탭의 "원격 명령 유예" 선택 상자에서 사용 안 함 / 10초 / 30초 / 1분 / 5분 / 10분 / 30분 중 선택. config.json에
grace_seconds(초, 5~3600, 기본 300) 추가,shutdown_grace는 그대로 on/off. 키가 없는 기존 config.json이나 값을 보내지 않는 구 WebUI는 기존(기본) 값을 유지 (#51) -
예약 출처 표시와 대체 알림 — 예약 탭·트레이 상태·토스트가 예약이 SmartThings 원격 명령의 유예인지 이 앱/WebUI에서 건 것인지 구분해 표시 (원격은 경고색). 새 예약이 기존 예약을 대체하면 "기존 예약 '종료'(이 앱)을 대체했습니다"를 표시하고 서비스 로그에 기록.
/api/scheduleGET에origin(ui|remote)과replaced추가 (#54)
개선 (데스크톱 앱)
- 예약 탭: 분 직접 입력을 없애고 프리셋(5/15/30/60/120분) 선택만 제공. 남은 시간을 큰 글자로 표시하고 [예약 취소]는 예약이 있을 때만 활성화 (#52)
- 탭 아이콘, 상단 상태 표시줄의 연결 상태 색 점(연결/끊김/연결 중), 명령 버튼 아이콘, 설정 탭을 서비스 설정 / 도구 / 앱 세 섹션으로 정리 (#53)
- 창 기본 크기를 640×800으로 조정해 설정 탭이 한국어/영어 모두 스크롤 없이 표시됨 (#53)
- 언어 전환 직후 "서비스 관리" 섹션이 아래 섹션 위에 겹쳐 보이던 문제와, 네트워크 탭의 긴 IPv6 주소 목록이 로드되면서 창 너비가 늘어나던 문제 수정 (#53)
수정
- 자동 업데이트 후 앱 재실행을 explorer.exe 경유에서 데스크톱 사용자 토큰(
CreateProcessWithTokenW) 기반으로 변경 — 재실행된 앱이 로그인 자동 시작(HKCU Run) 항목을 정상 갱신. 실패 시 기존 explorer.exe → 직접 실행 순으로 폴백 (#50)
변경
- 서비스 로그의 예약/유예 시간 표기가 분 고정에서
5 min/30 sec형식으로 변경
Full Changelog: v0.3.3...v0.3.4
v0.3.3
[v0.3.3]
새 기능
- 로그인 시 트레이 자동 시작 — 사용자 로그인 시 앱이 창 없이 트레이에만 상주 (
gui --minimized). 5분 유예 알림([바로 실행]/[취소])은 트레이 앱이 떠 있어야 표시되므로 기본 켬. 설정 탭 도구 → "로그인 시 트레이에 자동 시작"으로 끄기 가능. HKCU Run 등록이라 관리자 권한 불필요, 앱 시작마다 현재 exe 경로로 갱신 (#42) - 서비스가 트레이 앱을 깨움 — 원격(SmartThings) 전원 명령이 5분 유예로 예약되면 서비스가 로그인된 사용자 세션에서 트레이 앱(
gui --minimized)을 실행해 [바로 실행]/[취소] 토스트가 항상 표시됨. 이미 실행 중이면 조용히 무시(창을 앞으로 가져오지 않음), 앱/WebUI에서 만든 예약은 깨우지 않음 (#43) - 앱 내 자동 업데이트 — 업데이트 알림에서 [지금 업데이트]를 누르면 GitHub Release의 exe를 진행률과 함께 다운로드하고, 받은 파일의
version출력으로 버전을 검증한 뒤 UAC 승인 한 번으로 서비스 중지 → exe 교체(기존 exe는.old로 보관) → 서비스 재시작 → 앱 재실행까지 자동 진행. 실패 시 이전 exe로 자동 롤백, 단계별 기록은 exe 옆gui.log. 설정 탭 도구에 [업데이트 확인] 버튼 추가.dev빌드는 확인만 하고 교체하지 않음 (#40 2단계)
개선 (데스크톱 앱)
- 설정 탭: [저장] 버튼이 포트·시크릿·옵션이 실제로 바뀐 경우에만 활성화 (#44)
- 트레이: 아이콘 툴팁과 상태 메뉴 항목에 연결 상태와 활성 예약(명령·남은 시간) 표시 (#45)
- 예약 탭: 5 / 15 / 30 / 60분 프리셋 버튼 (#46)
- 로그 탭: 필터 입력(대소문자 무시), [로그 파일 열기] / [폴더 열기] 버튼 (#47)
- 서비스 설치: 실행 파일이 다운로드·바탕 화면·문서·임시 폴더 또는 사용자 프로필 루트에 있으면 경고하고 확인한 경우에만 설치 (#48)
CI
- GitHub Actions에 Go 빌드/모듈 캐시(actions/cache) 명시 적용, develop/main 푸시·PR에서 vet/test/빌드를 수행하는 CI 워크플로 추가 — 태그 릴리즈 빌드 시간 단축 (#49)
변경
- 업데이트 대화상자의 기본 버튼이 "다운로드 페이지 열기"에서 "지금 업데이트"로 변경 (릴리스 페이지 링크는 본문에 유지)
업그레이드 안내 (v0.3.2 → v0.3.3)
- v0.3.2에서는 exe를 직접 교체하세요 (서비스 중지 → 교체 → 시작). v0.3.3부터는 앱의 [지금 업데이트]로 자동 교체됩니다
- exe 교체 후 앱을 한 번 실행하면 로그인 자동 시작이 등록됩니다 (기존 설정은 그대로)
Full Changelog: v0.3.2...v0.3.3
v0.3.2
[v0.3.2]
새 기능
- 네이티브 데스크톱 앱 (Fyne) — 설정/명령/예약/네트워크/로그 5개 탭, WebUI와 동등 기능 (#33)
- 시스템 트레이 상주 — 왼쪽 클릭 = 창 열기, 우클릭 메뉴(열기/상태/빠른 명령/예약 취소/WebUI/종료), 창 닫기 = 트레이로 최소화 (#34)
- 원격 전원 명령 5분 유예 — SmartThings의 종료/재시작/절전/최대절전 명령을 5분 뒤 실행. Windows 알림의 [바로 실행]/[취소] 버튼, 트레이 메뉴, 앱 예약 탭에서 처리 가능. 앱/WebUI에서 직접 실행하는 명령과 강제 종료는 항상 즉시.
shutdown_grace설정 (기본 true) (#41) - 업데이트 자동 확인 — 시작 시 + 매일 GitHub Releases 확인, 새 버전 알림 (#40 1단계)
- WebUI 브라우저 접속 토글 —
webui_remote설정 (기본 false). 켜면 로컬+LAN에서 브라우저 접속 가능 (시크릿 필수, 방화벽 규칙 자동 관리), 끄면 데스크톱 앱 전용 (#38) - 한국어/영어 지원 (OS 언어 자동 감지 + 전환, 맑은고딕 시스템 폰트 사용)
- 서비스 관리를 앱에 내장 — 설치/시작/제거 (UAC 승격), 상태 자동 감지 (#35, #36)
변경
- 더블클릭 = 네이티브 앱 실행 (기존: PowerShell WPF 관리 패널 → 제거됨)
- 브라우저 WebUI는 기본 비활성 — 설정에서 "브라우저 접속 허용"을 켜야 사용 가능
- 빌드에
-H=windowsgui적용 — GUI 실행 시 콘솔창 없음 (CLI 출력은 유지) - 창 중복 실행 방지 — 재실행 시 기존 창을 앞으로 가져옴
- 로그 로테이션 기준 1MB → 512KB (백업 3개 유지, 총 ~2MB 상한)
수정
- 콘솔 모드에서 WebUI 포트가 잘못 계산되던 경쟁 조건 수정 (config 로드 전 시작)
- 앱에서 언어를 전환하면 설정 입력값이 비워지고 상태가 "연결 중..."에 머무는 문제 수정 — 전환 후 설정/연결 상태를 다시 불러오고 보고 있던 탭을 유지
- 트레이 메뉴에 "종료"와 Fyne 기본 "Quit"이 함께 표시되던 문제 수정
- 트레이 아이콘 왼쪽 클릭 시 메뉴가 뜨던 동작을 창 열기로 변경 (메뉴는 우클릭)
업그레이드 안내 (v0.3.x → v0.3.2)
- exe 교체만으로 업그레이드 가능 (서비스 중지 → 교체 → 시작). 서비스 재설치 불필요
- 기존 config.json 그대로 호환 — 새 설정은 기본값 적용 (
webui_remote=false,shutdown_grace=true) - 동작 변화 주의: 브라우저 WebUI가 기본 꺼짐 / SmartThings 전원 명령에 5분 유예가 기본 적용됨 (설정에서 끄기 가능)
Full Changelog: v0.3.1...v0.3.2
v0.3.1
[v0.3.1]
새 기능
- 더블클릭 GUI 서비스 관리 패널 (Install/Uninstall/Start/Open WebUI)
- 서비스 상태 실시간 표시 (Running/Stopped/Not installed)
- 상태에 따라 버튼 자동 전환 (Install ↔ Uninstall)
- 로딩 상태 표시 (Installing.../Starting.../Removing...)
- GUI 에러 발생 시 gui.log에 기록
개선
- svc.IsWindowsService()로 서비스/인터랙티브 세션 정확 판별
- CLI 명령어 그대로 유지 (install/uninstall/status/version/run)
Full Changelog: v0.3.0...v0.3.1