LG_THINQ_INTEGRATION - zero1ne-26/doc GitHub Wiki

LG ThinQ ๊ฐ€์ „ ์—ฐ๋™ โ€” HA ํ†ตํ•ฉ ยท REST ๋ฐ์ดํ„ฐ ์ทจ๋“ ยท ์ œ์–ด

LG ThinQ ๊ฐ€์ „(๊ณต๊ธฐ์ฒญ์ •๊ธฐ ๋“ฑ)์„ Home Assistant(HA)์— ์—ฐ๊ฒฐํ•˜๊ณ , ์™ธ๋ถ€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ HA REST API๋กœ ์ƒํƒœ๋ฅผ ์ฝ๊ณ  ์ œ์–ดํ•˜๋Š” ์ ˆ์ฐจ๋ฅผ ์ •๋ฆฌํ•œ ์‹ค๋ฌด ๊ฐ€์ด๋“œ๋‹ค. ์‹ค์ธก ์˜ˆ์‹œ๋Š” appStore/tablet-fe/ha-api.http(VS Code REST Client ํŒŒ์ผ) ๊ธฐ์ค€์ด๋ฉฐ, ๋ณธ๋ฌธ ์š”์ฒญ ๋ฒˆํ˜ธ(#0~#8)๋Š” ๊ทธ ํŒŒ์ผ์˜ ์š”์ฒญ ๋ฒˆํ˜ธ์™€ ์ผ์น˜ํ•œ๋‹ค. ๋ณธ ๋ฌธ์„œ๋Š” ๋…ผ์˜/์˜จ๋ณด๋”ฉ์šฉ ์ž๋ฃŒ๋‹ค. HA๊ฐ€ ์‹œ์Šคํ…œ์—์„œ ๊ฐ–๋Š” ์—ญํ• (์ƒํƒœ ์ €์žฅ์†Œ)์€ OSS_INTEGRATION.md, HAยทMQTT ๊ธฐ์ดˆ๋Š” ROBOT_ADAPTER_ONBOARDING.md๋ฅผ ์ฐธ๊ณ ํ•œ๋‹ค.

0. ์ „์ฒด ๊ทธ๋ฆผ โ€” ๋ฌด์—‡์ด ๋ฌด์—‡๊ณผ ํ†ต์‹ ํ•˜๋Š”๊ฐ€

LG ThinQ ๊ฐ€์ „ โ”€โ”€(Wi-Fi)โ”€โ”€โ–ถ LG ThinQ Cloud
                               โ–ฒ
                               โ”‚ ThinQ Connect API (LG PAT ํ† ํฐ)
                               โ–ผ
                        Home Assistant  โ† LG ThinQ integration ์ด ๊ธฐ๊ธฐ๋ฅผ ์—”ํ‹ฐํ‹ฐ๋กœ ํก์ˆ˜
                               โ–ฒ
                               โ”‚ REST API  /api/*  (Bearer HA_TOKEN)
                               โ–ผ
                 ํด๋ผ์ด์–ธํŠธ (ha-api.http ยท BFF ยท ์Šคํฌ๋ฆฝํŠธ ๋“ฑ)
  • ํ† ํฐ์ด ๋‘ ์ข…๋ฅ˜๋‹ค. โ‘  LG PAT(Personal Access Token): HA โ†” ThinQ Cloud ์—ฐ๊ฒฐ์šฉ, LG ๊ณ„์ •์—์„œ ๋ฐœ๊ธ‰. โ‘ก HA Long-Lived Access Token: ํด๋ผ์ด์–ธํŠธ โ†” HA REST API ์ธ์ฆ์šฉ, HA ์‚ฌ์šฉ์ž ํ”„๋กœํ•„์—์„œ ๋ฐœ๊ธ‰. ์„œ๋กœ ๋‹ค๋ฅธ ํ† ํฐ์ด๋ฉฐ ์šฉ๋„๋ฅผ ํ˜ผ๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • ์ œ์–ด๋Š” ํด๋ผ์šฐ๋“œ๋ฅผ ๊ฒฝ์œ ํ•œ๋‹ค. ํด๋ผ์ด์–ธํŠธ โ†’ HA(service ํ˜ธ์ถœ) โ†’ ThinQ Cloud โ†’ ๊ธฐ๊ธฐ ์ˆœ์„œ๋กœ ์ „๋‹ฌ๋˜๋ฏ€๋กœ, ๋กœ์ปฌ ๊ธฐ๊ธฐ ์ œ์–ด ๋Œ€๋น„ ์ง€์—ฐ์ด ์žˆ๊ณ  ์ธํ„ฐ๋„ท์ด ๋Š๊ธฐ๋ฉด ์ œ์–ด๋„ ๋Š๊ธด๋‹ค.
  • ๊ธฐ๊ธฐ๋Š” HA ์•ˆ์—์„œ ์—”ํ‹ฐํ‹ฐ(entity)๋กœ ๋‚˜ํƒ€๋‚œ๋‹ค. ์˜ˆ: ๊ณต๊ธฐ์ฒญ์ •๊ธฐ ์šด์ „ ๋ชจ๋“œ โ†’ select.gonggiceongjeonggi_operating_mode (๊ธฐ๊ธฐ ์ด๋ฆ„์˜ ๋กœ๋งˆ์ž ํ‘œ๊ธฐ + ๊ธฐ๋Šฅ๋ช…์œผ๋กœ ์ž๋™ ์ƒ์„ฑ).

1. ์—ฐ๊ฒฐ โ€” HA์— LG ThinQ ํ†ตํ•ฉ ์ถ”๊ฐ€

1.1 ์‚ฌ์ „ ์ค€๋น„

ํ•ญ๋ชฉ ๋‚ด์šฉ
ThinQ ์•ฑ ๊ธฐ๊ธฐ ๋“ฑ๋ก ์ œ์–ดํ•  ๊ฐ€์ „์ด LG ThinQ ๋ชจ๋ฐ”์ผ ์•ฑ์— ๋“ฑ๋กยท์˜จ๋ผ์ธ ์ƒํƒœ์—ฌ์•ผ ํ•œ๋‹ค (HA๊ฐ€ ๊ธฐ๊ธฐ๋ฅผ ์ง์ ‘ ์ฐพ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ThinQ ๊ณ„์ •์— ๋“ฑ๋ก๋œ ๊ธฐ๊ธฐ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค)
HA ๋ฒ„์ „ 2024.11 ์ด์ƒ โ€” ๊ณต์‹ LG ThinQ ํ†ตํ•ฉ(ThinQ Connect API ๊ธฐ๋ฐ˜)์ด ์ด ๋ฒ„์ „๋ถ€ํ„ฐ ๋‚ด์žฅ
LG ๊ณ„์ • ThinQ ์•ฑ์— ๋กœ๊ทธ์ธํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€ LG ๊ณ„์ •์œผ๋กœ PAT๋ฅผ ๋ฐœ๊ธ‰ํ•ด์•ผ ํ•œ๋‹ค

1.2 LG PAT(Personal Access Token) ๋ฐœ๊ธ‰

  1. ๋ธŒ๋ผ์šฐ์ €์—์„œ https://connect-pat.lgthinq.com ์ ‘์†
  2. ThinQ ์•ฑ๊ณผ ๋™์ผํ•œ LG ๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธ
  3. Add New Token โ†’ ํ† ํฐ ์ด๋ฆ„ ์ž…๋ ฅ(์˜ˆ: home-assistant) โ†’ ๊ถŒํ•œ ๋ฒ”์œ„ ์„ ํƒ ํ›„ ์ƒ์„ฑ
  4. ๋ฐœ๊ธ‰๋œ ํ† ํฐ ๋ฌธ์ž์—ด์„ ๋ณต์‚ฌํ•ด ๋‘”๋‹ค

1.3 HA์— ํ†ตํ•ฉ ์ถ”๊ฐ€

  1. HA ์›น UI โ†’ ์„ค์ • โ†’ ๊ธฐ๊ธฐ ๋ฐ ์„œ๋น„์Šค โ†’ ํ†ตํ•ฉ ์ถ”๊ฐ€
  2. LG ThinQ ๊ฒ€์ƒ‰ โ†’ ์„ ํƒ
  3. PAT ์ž…๋ ฅ + ๊ตญ๊ฐ€ ์„ ํƒ(๋Œ€ํ•œ๋ฏผ๊ตญ) โ†’ ์ œ์ถœ
  4. ThinQ ๊ณ„์ •์˜ ๊ธฐ๊ธฐ๋“ค์ด ์ž๋™์œผ๋กœ ๋“ฑ๋ก๋˜๊ณ , ๊ธฐ๊ธฐ๋ณ„ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค

1.4 ์—”ํ‹ฐํ‹ฐ ํ™•์ธ

๊ฐœ๋ฐœ์ž ๋„๊ตฌ โ†’ ์ƒํƒœ ํ™”๋ฉด์—์„œ ๊ธฐ๊ธฐ ์ด๋ฆ„์œผ๋กœ ๊ฒ€์ƒ‰ํ•˜๋ฉด ์ƒ์„ฑ๋œ ์—”ํ‹ฐํ‹ฐ ID๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ณต๊ธฐ์ฒญ์ •๊ธฐ ์˜ˆ:

์—”ํ‹ฐํ‹ฐ ๋„๋ฉ”์ธ ์šฉ๋„
select.gonggiceongjeonggi_operating_mode select ์šด์ „ ๋ชจ๋“œ (auto / dual_clean / circulator / clean)

โš ๏ธ ์—”ํ‹ฐํ‹ฐ ID๋Š” ThinQ์— ๋“ฑ๋ก๋œ ๊ธฐ๊ธฐ ์ด๋ฆ„์˜ ๋กœ๋งˆ์ž ํ‘œ๊ธฐ๋กœ ์ž๋™ ์ƒ์„ฑ๋œ๋‹ค. ๊ธฐ๊ธฐ ์ด๋ฆ„์„ ๋ฐ”๊พธ๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ํ™˜๊ฒฝ์— ์žฌ์„ค์น˜ํ•˜๋ฉด ID๊ฐ€ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์— ํ•˜๋“œ์ฝ”๋”ฉํ•˜์ง€ ๋ง๊ณ  ์„ค์ •/ํ™˜๊ฒฝ๊ฐ’์œผ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค.

2. HA API ํ† ํฐ ๋ฐœ๊ธ‰ (ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ)

REST API ํ˜ธ์ถœ์—๋Š” HA์˜ Long-Lived Access Token์ด ํ•„์š”ํ•˜๋‹ค.

  1. HA ์›น UI ๋กœ๊ทธ์ธ โ†’ ์ขŒ์ธก ํ•˜๋‹จ ํ”„๋กœํ•„ โ†’ ๋ณด์•ˆ ํƒญ
  2. ๋งจ ์•„๋ž˜ ์žฅ๊ธฐ ์•ก์„ธ์Šค ํ† ํฐ โ†’ ํ† ํฐ ์ƒ์„ฑ (์ด๋ฆ„์€ ์šฉ๋„๋ฅผ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ, ์˜ˆ: tablet-fe-bff)
  3. ์ƒ์„ฑ ์งํ›„ ํ•œ ๋ฒˆ๋งŒ ํ‘œ์‹œ๋˜๋ฏ€๋กœ ์ฆ‰์‹œ ๋ณต์‚ฌ โ†’ env ํŒŒ์ผ์— ๋ณด๊ด€
# .env (์ปค๋ฐ‹ ๊ธˆ์ง€)
HA_URL=http://<HA์ฃผ์†Œ>:8123
HA_TOKEN=eyJhbGciOi...
  • ์œ ํšจ๊ธฐ๊ฐ„ 10๋…„, ํ๊ธฐ๋Š” ๊ฐ™์€ ํ™”๋ฉด์—์„œ ์ฆ‰์‹œ ๊ฐ€๋Šฅ.
  • ํ† ํฐ ๊ถŒํ•œ = ๋ฐœ๊ธ‰ ์‚ฌ์šฉ์ž ๊ถŒํ•œ (ํ† ํฐ ๋‹จ์œ„ read-only ์Šค์ฝ”ํ”„ ์—†์Œ). ์กฐํšŒยท์ œ์–ด๋งŒ ํ•œ๋‹ค๋ฉด ๊ด€๋ฆฌ์ž ๊ถŒํ•œ ์—†๋Š” ์ „์šฉ ์‚ฌ์šฉ์ž๋ฅผ ๋งŒ๋“ค์–ด ๊ทธ ๊ณ„์ •์œผ๋กœ ๋ฐœ๊ธ‰ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค.

3. ๋ฐ์ดํ„ฐ ์ทจ๋“ โ€” REST ์กฐํšŒ

๋ชจ๋“  ์š”์ฒญ์€ Authorization: Bearer <HA_TOKEN> ํ—ค๋”๋ฅผ ๋ถ™์ธ๋‹ค. (ha-api.http #0~#3)

# ์—”๋“œํฌ์ธํŠธ ์šฉ๋„
0 GET /api/ ์—ฐ๊ฒฐยทํ† ํฐ ํ™•์ธ ({"message": "API running."})
1 GET /api/config HA ๋ฒ„์ „ยท์„ค์ • (ํ—ฌ์Šค์ฒดํฌ ๊ฒธ์šฉ)
2 GET /api/states ์ „์ฒด ์—”ํ‹ฐํ‹ฐ ์ƒํƒœ ๋ชฉ๋ก โ€” ์กด์žฌํ•˜๋Š” entity_id ํ›‘๊ธฐ
3 GET /api/states/<entity_id> ๋‹จ์ผ ์—”ํ‹ฐํ‹ฐ ์ƒํƒœ (์—†์œผ๋ฉด 404)

๋‹จ์ผ ์—”ํ‹ฐํ‹ฐ ์กฐํšŒ ์˜ˆ โ€” ๊ณต๊ธฐ์ฒญ์ •๊ธฐ ์šด์ „ ๋ชจ๋“œ:

GET {{haUrl}}/api/states/select.gonggiceongjeonggi_operating_mode
Authorization: Bearer {{haToken}}
{
  "entity_id": "select.gonggiceongjeonggi_operating_mode",
  "state": "auto",
  "attributes": {
    "options": ["auto", "dual_clean", "circulator", "clean"],
    "friendly_name": "๊ณต๊ธฐ์ฒญ์ •๊ธฐ Operating mode"
  },
  "last_changed": "2026-08-02T04:10:22.513Z",
  "last_updated": "2026-08-02T04:10:22.513Z"
}
  • state๋Š” ํ•ญ์ƒ string์ด๋‹ค โ€” ๊ธฐ๊ธฐ๊ฐ€ ์˜คํ”„๋ผ์ธ์ด๋ฉด "unavailable", ์ดˆ๊ธฐํ™” ์ „์ด๋ฉด "unknown"์ด ์˜ฌ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ๋Š” ์ด ๊ฐ’์„ ๋ฐฉ์–ด ์ฒ˜๋ฆฌํ•œ๋‹ค.
  • attributes.options๊ฐ€ ์ œ์–ด(ยง4)์— ๋„ฃ์„ ์ˆ˜ ์žˆ๋Š” ์œ ํšจ๊ฐ’ ๋ชฉ๋ก์ด๋‹ค โ€” ์ œ์–ด ์ „์— ์ด ์กฐํšŒ๋กœ ํ™•์ธํ•œ๋‹ค.
  • REST ์กฐํšŒ๋Š” ํด๋ง ๋ฐฉ์‹์ด๋‹ค. ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ›์•„์•ผ ํ•˜๋ฉด HA WebSocket API ๋˜๋Š” MQTT statestream์„ ๋ณ„๋„ ๊ฒ€ํ† ํ•œ๋‹ค(์ด ๋ฌธ์„œ ๋ฒ”์œ„ ๋ฐ–).

4. ์ œ์–ด โ€” service ํ˜ธ์ถœ

HA์—์„œ ์—”ํ‹ฐํ‹ฐ ์ œ์–ด๋Š” ์ƒํƒœ๋ฅผ ์ง์ ‘ ์“ฐ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ๋„๋ฉ”์ธ๋ณ„ service ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค:

POST /api/services/<๋„๋ฉ”์ธ>/<์„œ๋น„์Šค>     body: { "entity_id": "...", ...ํŒŒ๋ผ๋ฏธํ„ฐ }

์–ด๋–ค ๋„๋ฉ”์ธ์— ์–ด๋–ค ์„œ๋น„์ŠคยทํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์žˆ๋Š”์ง€๋Š” GET /api/services(#4)๋กœ ํ™•์ธํ•œ๋‹ค.

4.1 select ์—”ํ‹ฐํ‹ฐ โ€” ์šด์ „ ๋ชจ๋“œ ๋ณ€๊ฒฝ (#5ยท#6)

POST {{haUrl}}/api/services/select/select_option
Authorization: Bearer {{haToken}}
Content-Type: application/json

{
  "entity_id": "select.gonggiceongjeonggi_operating_mode",
  "option": "dual_clean"
}
  • option์€ ยง3 ์กฐํšŒ ์‘๋‹ต์˜ attributes.options์— ์žˆ๋Š” ๊ฐ’๋งŒ ์œ ํšจํ•˜๋‹ค. ๋ชฉ๋ก์— ์—†๋Š” ๊ฐ’์„ ๋ณด๋‚ด๋ฉด 400์ด ์˜จ๋‹ค.
  • ๊ณต๊ธฐ์ฒญ์ •๊ธฐ ์šด์ „ ๋ชจ๋“œ ์œ ํšจ๊ฐ’: auto / dual_clean / circulator / clean.

4.2 ๋ฒ”์šฉ ์ผœ๊ธฐ/๋„๊ธฐ/ํ† ๊ธ€ (#7)

on/offํ˜• ์—”ํ‹ฐํ‹ฐ(switchยทlightยทfan ๋“ฑ)๋Š” ๋„๋ฉ”์ธ์„ ๋ชฐ๋ผ๋„ homeassistant ๋„๋ฉ”์ธ์œผ๋กœ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค:

POST {{haUrl}}/api/services/homeassistant/turn_off
Authorization: Bearer {{haToken}}
Content-Type: application/json

{ "entity_id": "switch.demo_plug" }

turn_on / turn_off / toggle ์…‹ ๋‹ค ๊ฐ™์€ ํ˜•ํƒœ๋‹ค.

4.3 ์‘๋‹ต ํ•ด์„

service ํ˜ธ์ถœ์˜ ์‘๋‹ต์€ ์ด ํ˜ธ์ถœ๋กœ ์ƒํƒœ๊ฐ€ ๋ฐ”๋€ ์—”ํ‹ฐํ‹ฐ ๋ชฉ๋ก(๋ฐฐ์—ด) ์ด๋‹ค. ThinQ์ฒ˜๋Ÿผ ํด๋ผ์šฐ๋“œ๋ฅผ ๊ฒฝ์œ ํ•˜๋Š” ๊ธฐ๊ธฐ๋Š” ๋ฐ˜์˜์ด ๋น„๋™๊ธฐ๋ผ ๋นˆ ๋ฐฐ์—ด []์ด ์™€๋„ ์‹คํŒจ๊ฐ€ ์•„๋‹ ์ˆ˜ ์žˆ๋‹ค โ€” ์‹ค์ œ ๋ณ€๊ฒฝ ์—ฌ๋ถ€๋Š” GET /api/states/<entity_id>(#3) ์žฌ์กฐํšŒ๋กœ ํ™•์ธํ•œ๋‹ค.

4.4 ์ƒํƒœ ์ง์ ‘ ์“ฐ๊ธฐ๋Š” ์ œ์–ด๊ฐ€ ์•„๋‹ˆ๋‹ค (#8)

โš ๏ธ POST /api/states/<entity_id>๋Š” HA ์ƒํƒœ ๋จธ์‹ ์˜ ๊ฐ’๋งŒ ๋ฎ์–ด์“ธ ๋ฟ ์‹ค์ œ ๊ธฐ๊ธฐ๋ฅผ ์›€์ง์ด์ง€ ์•Š๋Š”๋‹ค. ๊ธฐ๊ธฐ ์ œ์–ด์— ์“ฐ๋ฉด "HA ํ™”๋ฉด์ƒ์œผ๋ก  ๋ฐ”๋€Œ์—ˆ๋Š”๋ฐ ๊ธฐ๊ธฐ๋Š” ๊ทธ๋Œ€๋กœ"์ธ ์ƒํƒœ๊ฐ€ ๋œ๋‹ค. ์šฉ๋„๋Š” sensor์ฒ˜๋Ÿผ ์ œ์–ด service๊ฐ€ ์—†๋Š” ์—”ํ‹ฐํ‹ฐ์— ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ์ž…ํ•˜๋Š” ๊ฒƒ๋ฟ์ด๋‹ค (์กด์žฌํ•˜์ง€ ์•Š๋Š” entity_id๋ฉด ์ƒˆ๋กœ ์ƒ์„ฑ๋œ๋‹ค).

5. ha-api.http๋กœ ๋ฐ”๋กœ ํ…Œ์ŠคํŠธํ•˜๊ธฐ

appStore/tablet-fe/ha-api.http์— ์œ„ ์š”์ฒญ๋“ค์ด ๋ฒˆํ˜ธ(#0~#8) ์ˆœ์œผ๋กœ ์ค€๋น„๋˜์–ด ์žˆ๋‹ค.

  1. VS Code REST Client ํ™•์žฅ(humao.rest-client) ์„ค์น˜
  2. env ์—ฐ๊ฒฐ โ€” {{$dotenv VAR}}๋Š” .http ํŒŒ์ผ๊ณผ ๊ฐ™์€ ํด๋”์˜ .env๋งŒ ์ฝ๋Š”๋‹ค(๊ฒฝ๋กœ ์„ค์ • ์—†์Œ). .env.local์„ ์“ฐ๋Š” ๋ ˆํฌ์—์„œ๋Š” ์‹ฌ๋ณผ๋ฆญ ๋งํฌ๋กœ ์—ฐ๊ฒฐํ•œ๋‹ค:
    ln -s .env.local .env   # .gitignore ์˜ .env* ๊ทœ์น™์œผ๋กœ ์ปค๋ฐ‹๋˜์ง€ ์•Š์Œ
  3. {{haUrl}} ์œ„์— ๋งˆ์šฐ์Šค๋ฅผ ์˜ฌ๋ ค ๊ฐ’์ด ํ•ด์„๋˜๋Š”์ง€ ํ™•์ธ โ†’ ๊ฐ ์š”์ฒญ ์œ„ Send Request ํด๋ฆญ
  4. ๊ถŒ์žฅ ์ˆœ์„œ: #0(์—ฐ๊ฒฐ ํ™•์ธ) โ†’ #2(entity_id ํ›‘๊ธฐ) โ†’ #3(๋‹จ์ผ ์กฐํšŒ, options ํ™•์ธ) โ†’ #5/#6(๋ชจ๋“œ ๋ณ€๊ฒฝ) โ†’ #3 ์žฌ์กฐํšŒ(๋ฐ˜์˜ ํ™•์ธ)

6. ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

์ฆ์ƒ ์›์ธ ยท ์กฐ์น˜
401 Unauthorized HA_TOKEN ๋ˆ„๋ฝ/์˜คํƒ€/ํ๊ธฐ๋จ. #0์œผ๋กœ ํ† ํฐ๋ถ€ํ„ฐ ๊ฒ€์ฆ
404 Not Found entity_id ์˜คํƒ€ ๋˜๋Š” ๋ฏธ์ƒ์„ฑ. #2 ์ „์ฒด ๋ชฉ๋ก์—์„œ ์‹ค์ œ ID ํ™•์ธ
400 Bad Request (select) option ๊ฐ’์ด attributes.options์— ์—†์Œ. #3์œผ๋กœ ์œ ํšจ๊ฐ’ ํ™•์ธ
์ œ์–ด ์‘๋‹ต์ด [] ์‹คํŒจ ์•„๋‹˜(ํด๋ผ์šฐ๋“œ ๊ฒฝ์œ  ๋น„๋™๊ธฐ ๋ฐ˜์˜ ๊ฐ€๋Šฅ) โ€” #3 ์žฌ์กฐํšŒ๋กœ ํŒ๋‹จ
state: "unavailable" ๊ธฐ๊ธฐ ์˜คํ”„๋ผ์ธ ๋˜๋Š” ThinQ Cloud ์—ฐ๊ฒฐ ๋Š๊น€. ThinQ ์•ฑ์—์„œ ๊ธฐ๊ธฐ ์ƒํƒœ ํ™•์ธ
ํ†ตํ•ฉ ์ž์ฒด๊ฐ€ ์ธ์ฆ ์˜ค๋ฅ˜ LG PAT ํ๊ธฐ/๋งŒ๋ฃŒ โ€” ์„ค์ • โ†’ ๊ธฐ๊ธฐ ๋ฐ ์„œ๋น„์Šค โ†’ LG ThinQ์—์„œ ์žฌ์ธ์ฆ(PAT ์žฌ๋ฐœ๊ธ‰)

โš ๏ธ HA_TOKENยทLG PAT๋Š” ์ ˆ๋Œ€ ์ €์žฅ์†Œ์— ์ปค๋ฐ‹ํ•˜์ง€ ์•Š๋Š”๋‹ค. env ํŒŒ์ผ(์„œ๋ฒ„ env)์—๋งŒ ๋‘๊ณ , .http ํŒŒ์ผ์—๋Š” {{$dotenv}} ์ฐธ์กฐ๋งŒ ๋‚จ๊ธด๋‹ค.

7. ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ ์„œ๋ฒ„ ยท ๋ฐฑ์˜คํ”ผ์Šค ์—ฐ๋™ (2026-08-29)

์„œ๋ฒ„๊ฐ€ ์œ„ REST API๋ฅผ ๋Œ€์‹  ํ˜ธ์ถœํ•˜๊ณ , ๋ฐฑ์˜คํ”ผ์Šค LG ๊ฐ€์ „ ๊ด€๋ฆฌ(/lg-appliances)์—์„œ ๊ฐ€์ „๋ณ„ ํ…Œ์ŠคํŠธ๋ฅผ ํ•œ๋‹ค.

ํ•ญ๋ชฉ ๋‚ด์šฉ
์„œ๋ฒ„ env HA_URL(๊ธฐ๋ณธ http://home-assistant:8123, ๊ฐ™์€ compose) ยท HA_TOKEN(HA Long-Lived Access Token โ€” devops GitHub Secret/Variable BE_HA_TOKEN์ด deploy ์›Œํฌํ”Œ๋กœ env โ†’ compose๋กœ ์ฃผ์ž…, ๋˜๋Š” ๋Ÿฌ๋„ˆ ~/orchestration-server.env). ํ† ํฐ์€ ์„œ๋ฒ„์—๋งŒ ์žˆ๊ณ  ๋ธŒ๋ผ์šฐ์ €๋กœ ๋‚ด๋ ค๊ฐ€์ง€ ์•Š๋Š”๋‹ค
์–ด๋“œ๋ฏผ API GET /api/admin/ha/status(์—ฐ๊ฒฐยท๋ฒ„์ „) ยท GET /api/admin/ha/entities?q=&domain=(์ „์ฒด ์—”ํ‹ฐํ‹ฐ ๊ฒ€์ƒ‰) ยท GET /api/admin/ha/entities/{entity_id} ยท POST /api/admin/ha/services/{domain}/{service} {entity_id, data} โ€” ํ˜ธ์ถœ ํ›„ 0.7์ดˆ ๋’ค ์žฌ์กฐํšŒํ•œ after๋ฅผ ํ•จ๊ป˜ ๋Œ๋ ค์ค€๋‹ค(ยง4.3 ๋น„๋™๊ธฐ ๋ฐ˜์˜)
๊ฐ€์ „ ๋งคํ•‘ lg_appliances ํ…Œ์ด๋ธ”(093): ์Šคํƒ€์ผ๋Ÿฌ / ๊ณต๊ธฐ์ฒญ์ •๊ธฐ / ๋ƒ‰์žฅ๊ณ  3ํ–‰ ๊ณ ์ •. entities = ๊ธฐ๋Šฅ ํ‚ค โ†’ entity_id JSON. GET/PUT /api/admin/lg-appliances/{id}, GET โ€ฆ/{id}/states
๋ฐฑ์˜คํ”ผ์Šค ๊ฐ€์ „ ์นด๋“œ๋งˆ๋‹ค ๊ธฐ๋Šฅ(์Šคํƒ€์ผ๋Ÿฌ: ํ–‰์ • ๋™์ž‘ยท์ฝ”์Šคยท์ข…๋ฃŒ ์˜ˆ์•ฝยท์ „์› / ๊ณต๊ธฐ์ฒญ์ •๊ธฐ: ์šด์ „ ๋ชจ๋“œยท์ „์›ยทํ’๋Ÿ‰ยท๋ฏธ์„ธ๋จผ์ง€ / ๋ƒ‰์žฅ๊ณ : ๋ƒ‰์žฅยท๋ƒ‰๋™ ์˜จ๋„ยท๊ธ‰์†ยท๋ฌธ)์— ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ง€์ •ํ•˜๋ฉด ๋„๋ฉ”์ธ์— ๋งž๋Š” ์ปจํŠธ๋กค์ด ์ž๋™์œผ๋กœ ๋œฌ๋‹ค โ€” selectโ†’options ๋ฒ„ํŠผ, numberโ†’๊ฐ’ ์ž…๋ ฅ(number.set_value), switch/fan/lightโ†’์ผœ๊ธฐยท๋„๊ธฐยทํ† ๊ธ€(homeassistant.*), climateโ†’์˜จ๋„(climate.set_temperature)ยท๋ชจ๋“œ, buttonโ†’press, sensorโ†’์ฝ๊ธฐ ์ „์šฉ. ์ž„์˜ ์„œ๋น„์Šค ํ˜ธ์ถœยท์†์„ฑ ๋ณด๊ธฐ๋„ ๊ฐ€๋Šฅ

์—”ํ‹ฐํ‹ฐ ID๋Š” ยง1.4๋Œ€๋กœ ํ™˜๊ฒฝ๋งˆ๋‹ค ๋‹ค๋ฅด๋ฏ€๋กœ ์ฝ”๋“œ์— ์—†๊ณ  ๋ฐฑ์˜คํ”ผ์Šค์—์„œ ์ง€์ •ํ•œ๋‹ค. HA์— LG ThinQ ํ†ตํ•ฉ(ยง1)์ด ๋จผ์ € ์ถ”๊ฐ€๋ผ ์žˆ์–ด์•ผ ํƒ์ƒ‰๊ธฐ์— ๊ธฐ๊ธฐ๊ฐ€ ๋ณด์ธ๋‹ค. | ์„ ํƒ์ง€ ์ „์› ์ œ์–ด | ํƒœ์Šคํฌ/์ด๋ฒคํŠธ ์„ ํƒ์ง€์— lg_appliance_id(lg-styler | lg-air-purifier | lg-refrigerator) + lg_power(on | off)๋ฅผ ๋‘๋ฉด(094), ํƒœ๋ธ”๋ฆฟ์ด orchestration/{sessionId}/task/option/select ยท event/option/select๋กœ ๊ทธ ์„ ํƒ์ง€๋ฅผ ๊ณ ๋ฅผ ๋•Œ ์„œ๋ฒ„๊ฐ€ ํ•ด๋‹น ๊ฐ€์ „์˜ entities.power ์—”ํ‹ฐํ‹ฐ์— homeassistant.turn_on/turn_off๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค. SPOT/๋ฐ˜๋ ค๋กœ๋ด‡ ๋ช…๋ น๊ณผ ๋…๋ฆฝ์ด๋ฉฐ ์‘๋‹ต(โ€ฆ/select/response)์—๋Š” ์˜ํ–ฅ ์—†์Œ. power ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋ฏธ๋งคํ•‘์ด๋ฉด ๋กœ๊ทธ๋งŒ ๋‚จ๊ธฐ๊ณ  ๋ฌด์‹œ | | ๋„์ฐฉ ์ž๋™ํ™” | arrival_automation_actions.device_type = 'lg'(096), action = on \| off, params_json = {"appliance_id": "lg-โ€ฆ"}. ์„ธ์…˜์ด ๊ทœ์น™์˜ ์žฅ์†Œ์— ๋„์ฐฉํ•˜๋ฉด ๋””๋ฐ”์ด์Šค ํ(lg:{appliance_id} ๊ทธ๋ฃน)์—์„œ ์•ž ์•ก์…˜ ์™„๋ฃŒ ํ›„ HA homeassistant.turn_on/off๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ํ˜ธ์ถœ ์„ฑ๊ณต์„ ์™„๋ฃŒ๋กœ ๊ธฐ๋กํ•œ๋‹ค(ack ์—†์Œ). ๋ฐฑ์˜คํ”ผ์Šค ์ž๋™ํ™” ์—๋””ํ„ฐ์—์„œ ๋””๋ฐ”์ด์Šค "LG ๊ฐ€์ „" ์„ ํƒ |

โš ๏ธ **GitHub.com Fallback** โš ๏ธ