νκ΅ κ±°μ£Όμλ₯Ό μν Home Assistant ν΅ν© β μ κΈ°Β·μλΒ·κ°μ€Β·λ μ¨Β·μ¬λΒ·μ½κ΅Β·νκ΅ κΈμΒ·μ€μκ° λμ€κ΅ν΅κΉμ§, νκ΅μμλ§ μΈ μ μλ 15κ°μ§ 곡곡 μλΉμ€λ₯Ό ν ν¨ν€μ§λ‘.
π°π· νκ΅μ΄ (μ΄ νμ΄μ§) Β· π¬π§ English README
π¬π§ English summary
A Home Assistant custom integration for Korean residents and expats. Exposes 15 Korea-only public services (KEPCO electricity, Seoul water, city gas, KMA weather, disaster alerts, NMC pharmacy, NEIS school meals, Seoul subway + Seoul Bus official API + nationwide bus via KakaoMap, AirKorea air quality, Opinet fuel prices, earthquake warnings) as native HA entities β sensors, weather entities, events, calendars.
All Korean public APIs are free; service keys are obtained from data.go.kr, safetydata.go.kr, opinet.co.kr, open.neis.go.kr, and data.seoul.go.kr β guides below link directly to each portal's search page.
Optional LLM integration lets you ask in natural Korean ("μ§κΈ λ―ΈμΈλ¨Όμ§ μ΄λ?", "μ€λ κΈμ λμΌ?") via HA's Assist conversation agent.
μ MY HACS λ±μ§λ₯Ό λλ₯΄λ©΄ μλμΌλ‘ HAκ° μ΄λ¦½λλ€ β DOWNLOAD β μ¬μμ.
HACSκ° μμΌμλ€λ©΄ β HACS 곡μ μ€μΉ κ°μ΄λ λ¨Όμ .
μ€μ β κΈ°κΈ° λ° μλΉμ€ β + ν΅ν© ꡬμ±μμ μΆκ°
β κ²μμ°½μ νκ΅ μ»΄ν¬λνΈ ν€νΈ (μλ¬Έ λλ©μΈ kr_component_kit λ κ°λ₯)
β π¨ μμ μλ¦Ό μ ν β μλ/μꡰꡬ/μλ©΄λ μ ν β μ μΆ
κ°λ°μ λꡬ β μν μμ μΉν μ΄λ¦ μ΅μ μμ μλ¦Ό κ²μ β stateμ κ°μ₯ μ΅κ·Ό νμλΆ μμ λ©μμ§ νμ.
μ€λΉλμλ©΄ π API ν€ λ°κΈ κ°μ΄λλλ‘ λ€λ₯Έ 12κ°λ₯Ό νλμ© μΆκ°νμλ©΄ λ©λλ€.
| μλΉμ€ | μΉ΄ν κ³ λ¦¬ | API ν€ | λΉκ³ |
|---|---|---|---|
| π μ½κ΅ | μν | β data.go.kr | μλ/μκ΅°κ΅¬λ³ μ½κ΅ + μ€μκ° μμ μ€ |
| π¨ μμ μλ¦Ό | μμ | β λΆνμ | νμλΆ μμ μλ¦Ό (μ€ν¬λν) |
| π’ μ¬λλ¬Έμ | μμ | β safetydata.go.kr | μ¬λλ¬Έμ μ€μκ° |
| πͺοΈ κΈ°μνΉλ³΄ | μμ | β data.go.kr | νΈμ°/κ°ν/νν/νμΌ 12μ’ |
| π μ§μ§ | μμ | β data.go.kr | λ°κ²½+κ·λͺ¨ νν° |
| β κΈ°μμ² λλ€μ보 | λ μ¨ | β data.go.kr | HA Weather μΉ΄λ νΈν |
| π«οΈ μμ΄μ½λ¦¬μ | λ μ¨ | β data.go.kr (2건) | PM10/PM2.5 + ν΅ν©λκΈ°μ§μ§μ |
| β‘ νκ΅μ λ ₯ (KEPCO) | μ νΈ | β (λ³ΈμΈ κ³μ ) | μ¬μ©λ + μκΈ |
| π§ μ리μ (μμΈ μμλ) | μ νΈ | β (μμ©κ°λ²νΈ) | μμΈλ§ |
| π κ°μ€μ± (λμκ°μ€) | μ νΈ | β (λͺ¨λ°μΌ μ± ν ν°) | ν¨ν· μΊ‘μ² νμ |
| β½ μ κ° (Opinet) | μν | β opinet.co.kr | μλλ³ νκ· /μ΅μ κ° |
| π« νκ΅ (NEIS) | μν | β open.neis.go.kr | κΈμΒ·μκ°νΒ·νμ¬μΌμ |
| π λμ€κ΅ν΅ | μν | λΆλΆ | μ§νμ² : μμΈ ν€ / λ²μ€: ν€ λΆνμ (μΉ΄μΉ΄μ€λ§΅) |
| π μμΈλ²μ€ (곡μ API) | μν | β data.go.kr | ARS-ID λ¨μ λμ°©μ 보 + μ΅μ μμ μ λ₯μ₯ μΆκ°/μ κ±° |
| π νκ΅ λ²μ€ (μ κ΅) | μν | β λΆνμ | μΉ΄μΉ΄μ€λ§΅ λͺ¨λ°μΌ β μ λ₯μ₯ μ΄λ¦ κ²μ UI, μ κ΅ |
π‘ ν΅μ¬: λͺ¨λ μλΉμ€λ λ¬΄λ£ μ λΆΒ·κ³΅κ³΅κΈ°κ΄ OpenAPIλ₯Ό μ¬μ©ν©λλ€. κ²°μ Β·κ³ΌκΈ μΌμ μμ.
β οΈ μμ£Ό λ°μνλ μ€μ 3κ°μ§
- μ¬λλ¬Έμλ
safetydata.go.kr(μμ λ°μ΄ν°ν¬νΈ) βdata.go.kr(곡곡λ°μ΄ν°ν¬νΈ) κ³Ό λ€λ₯Έ ν¬νΈ. κ³μ Β·ν€ λΆλ¦¬.- κ°μ
data.go.krμμμλ λ°μ΄ν°μ λ§λ€ νμ©μ μ²μ λ°λ‘ β μ½κ΅ μ μ² ν€λ‘ κΈ°μνΉλ³΄ νΈμΆνλ©΄ 403.- μ μ² μ§ν νμ±νκΉμ§ 1~2μκ° κ±Έλ¦΄ μ μμ (νΉν μ΄μκΈ°κ΄ ν€).
κ° μλΉμ€μ λ°λ‘ κ²μ λ§ν¬λ ν΄λ¦ ν λ²μ ν΄λΉ ν¬νΈ κ²μ κ²°κ³Ό νμ΄μ§λ‘ μ΄λν©λλ€ (λΈλΌμ°μ κ° νκ΅μ΄ μλ μΈμ½λ©).
| νλͺ© | κ° |
|---|---|
| π ν¬νΈ | 곡곡λ°μ΄ν°ν¬νΈ (data.go.kr) |
| π λ°λ‘ κ²μ | π μ κ΅ μ½κ΅ κ²μ κ²°κ³Όλ‘ μ΄λ |
| κ²μμ΄ | μ κ΅ μ½κ΅ λλ μ½κ΅ μ 보 |
| μ΄μκΈ°κ΄ | κ΅λ¦½μ€μμλ£μ (μ½λ B552657) |
| μ νν λ°μ΄ν°μ λͺ | κ΅λ¦½μ€μμλ£μ_μ κ΅ μ½κ΅ μ 보 μ‘°ν μλΉμ€ |
| μ½λ νΈμΆ endpoint | apis.data.go.kr/B552657/ErmctInsttInfoInqireService/getParmacyListInfoInqire |
μ μ² λ¨κ³: νμκ°μ β μ κ²μ λ§ν¬ ν΄λ¦ β λ°μ΄ν°μ μ ν β νμ©μ μ² β λ§μ΄νμ΄μ§ β μ€νAPI β μΈμ¦ν€ λ°κΈνν© β μΌλ° μΈμ¦ν€(Decoding) λ³΅μ¬ β HA μ½κ΅ νλͺ©μ κ·Έλλ‘ λΆμ¬λ£κΈ°.
| νλͺ© | κ° |
|---|---|
| π ν¬νΈ | νμ μμ λΆ μμ λ°μ΄ν°κ³΅μ νλ«νΌ (safetydata.go.kr) |
| μ΄μκΈ°κ΄ | νμ μμ λΆ |
| μ νν λ°μ΄ν°μ λͺ | νμ μμ λΆ_κΈ΄κΈμ¬λλ¬Έμ |
| μ½λ νΈμΆ endpoint | /V2/api/DSSP-IF-00247 |
| λ°κΈ λ°©μ | μ΄μμ κ²ν ν λ°κΈ (μ¦μ μλ λ°κΈ β, 1~3 μμ μΌ) |
| μΌμΌ νΈμΆ νλ | κΈ°λ³Έ 1,000건. ν΅ν©μ 5λΆ ν΄λ§μ΄λΌ 288건/μΌ μ¬μ© β μΆ©λΆ |
| ν€ μ ν¨κΈ°κ° | 1λ (λ§λ£ ν λ§μ΄νμ΄μ§μμ μ¬λ°κΈ β λ§λ£μΌμ νλ©΄μμ νμΈ) |
| ν€ νν | λ¨μΌ ννλ§ μ 곡 (data.go.kr μ²λΌ Decoding/Encoding λ κ°μ§ β) |
| IP νμ |
β οΈ μμ λ°μ΄ν°κ³΅μ νλ«νΌμ 곡곡λ°μ΄ν°ν¬νΈκ³Ό λ€λ₯Έ μ¬μ΄νΈμ λλ€. μ΄λ―Έdata.go.krκ³μ μ΄ μμ΄λ λ³λ κ°μ μ΄ νμν©λλ€.
safetydata.go.kr νμκ°μ
. data.go.kr κ³μ μΌλ‘λ λ‘κ·ΈμΈλμ§ μμ΅λλ€.
μλ¨ κ²μμ°½μ μ¬λλ¬Έμ β κ²μ κ²°κ³Ό μΉ΄λλ₯Ό 보면 λ κ°κ° λμ΅λλ€:
| μΉ΄λ | μ¬μ© μ¬λΆ |
|---|---|
νμ μμ λΆ_κΈ΄κΈμ¬λλ¬Έμ (μ‘°ν 5λ§+ / λ€μ΄λ‘λ 28M / #μ¬λλ¬Έμ νκ·Έ) |
β μ΄κ±Έ μ μ² |
μ¬λλ¬Έμ(μ보) (μ‘°ν 900+ / νκ·Έ #-1) |
β endpoint μ½λκ° λ¬λΌ ν΅ν©κ³Ό νΈν μ λ¨ |
μ¬λ°λ₯Έ μΉ΄λ ν΄λ¦ β μμΈ νμ΄μ§μμ endpoint κ° DSSP-IF-00247 μΈμ§ ν λ² νμΈ.
μμΈ νμ΄μ§ β μ€νAPI νμ©μ μ² λ²νΌ β νΌ μμ±:
β νμ©λͺ©μ (νμ)
- μΉ΄ν
κ³ λ¦¬:
μ±κ°λ° (λͺ¨λ°μΌ, μ루μ λ±)κΆμ₯ - μ€λͺ μμ: "νμ΄μμ€ν΄νΈ(Home Assistant) μ»΄ν¬λνΈλ‘ κ°μ‘±Β·λ³ΈμΈμκ² κΈ΄κΈμ¬λλ¬Έμ μλ¦Όμ λ°κ² ν λͺ©μ "
β‘ ν루 μ΅λ νΈμΆ νμ (νμ)
1000μ λ ₯. ν΅ν©μ΄ 5λΆ μ£ΌκΈ°λ‘ 288ν/μΌλ§ μ¬μ©νλ―λ‘ μΆ©λΆν©λλ€.
β’ μμ΄νΌ (νμ) β κ°μ₯ μ€μν λΆλΆ νΈμΆμ΄ λ€μ΄μ¬ HA μλ²μ 곡μΈ(μΈλΆ) IP λ₯Ό λ±λ‘ν΄μΌ ν©λλ€. λ±λ‘ IPμ μ€μ νΈμΆ IPκ° λ€λ₯΄λ©΄ ν€κ° λ°κΈλΌλ 403 κ±°λΆ.
| μ΅μ | μ λ ₯ μμ | μΆμ²λ |
|---|---|---|
| κ°μΈ IP | 121.123.45.67 |
κ°μ₯ μ격. νμ§λ§ νκ΅ κ°μ μ© μΈν°λ·μ dynamic IP λΌ λ©°μΉ ~λͺ λ¬ μμ λ°λ β μ¬μ μ² νμ |
| λμ νμ© | 121.123.*.* |
ISPκ° λΉμ·ν λμ μμμ κ°±μ ν΄μ£Όλ κ²½μ° μμ . μΌλ°μ μΌλ‘ 무λ |
| μ 체 νμ© | *.*.*.* |
β κ°μΈ μ¬μ©μ μΆμ² β IP λ³κ²½ μ κ²½ μ μ¨λ λ¨. ν€ μμ²΄κ° λΉλ°μ΄λΌ 보μ μν₯ λ―Έλ―Έ |
π HA μλ²μ κ³΅μΈ IP νμΈ λ°©λ²: λΆκ°κΈ°λ₯ β Terminal & SSH (λλ SSHλ‘ μ μ) β λ€μ λͺ λ Ή μ€ν:
curl -s https://api.ipify.orgμΆλ ₯λ IPκ° μ μ²μμ λ£μ κ°.
β£ λΌμ΄μ μ€ λμ β μ΄μ©μ μ² λ²νΌ ν΄λ¦.
λ§μ΄νμ΄μ§ β "λ°μ΄ν° νμ©μ μ² λ΄μ" μμ μν νμΈ:
- "μΉμΈ λκΈ° μ€μ λλ€" β μ΄μμ κ²ν μ€. μλ λ°κΈμ΄ μλλ―λ‘ μμ μΌ κΈ°μ€ 1~3μΌ μ λ λκΈ° μμ.
- "λ°κΈλ¨" β μλΉμ€ν€ κ°μ΄ λ ΈμΆλκ³ ν€ μ¬μ© κ°λ₯.
λ§μ΄νμ΄μ§ β λ°κΈλ ν€ μ "κ° λ³΅μ¬νκΈ°" ν΄λ¦ β HA ν΅ν© μΆκ° μ μ¬λλ¬Έμ μ ν β μΈμ¦ν€ νλμ κ·Έλλ‘ λΆμ¬λ£κΈ°.
π‘ safetydata.go.kr μ ν€λ₯Ό ν κ°μ§ ννλ‘λ§ μ 곡ν©λλ€ (data.go.kr μ Decoding/Encoding κ΅¬λΆ μμ). "κ° λ³΅μ¬νκΈ°" λ‘ λ°μ λ¬Έμμ΄μ κ·Έλλ‘ λΆμ¬λ£μΌλ©΄ λ©λλ€. ν΅ν© μ½λκ° λ΄λΆμ μΌλ‘ URL μΈμ½λ©μ μλ μ²λ¦¬ν©λλ€.
- νΈμΆλ λͺ¨λν°λ§: λ§μ΄νμ΄μ§ νλ©΄μ
μΌμΌνΈμΆλ / νΈμΆλνμ β μ μ«μκ° νλ(1000), λ€ μ«μκ° νμ¬κΉμ§ λμ μ¬μ© νμ (0μ΄λ©΄ "μ΅λ" κ° μλλΌ "μμ§ μ μ"). νλ μ΄κ³Ό μ λ€μ λ 0μ 리μ . - IP λ³κ²½ μ μ²: κ°μ μ© dynamic IP κ° λ°λ κ²½μ° λ§μ΄νμ΄μ§ β ν΄λΉ ν€ β λͺ©λ‘ λ³κ²½μ μ² β IP νλ μμ .
β οΈ λ³κ²½ μμ μ΄μμ κ²ν κ±°μΉ¨. μμ£Ό λ°λλ€λ©΄ μ²μλΆν°*.*.*.*λ‘ λ³κ²½ μ μ² κΆμ₯. - ν€ λ§λ£ (1λ ): λ§λ£μΌμ λλ μ μ λ§μ΄νμ΄μ§ β λ³κ²½μ μ²μΌλ‘ κ°±μ κ°λ₯. λ§λ£λλ©΄ 401 λ°μ.
| μ¦μ | μμΈ ν보 | ν΄κ²° |
|---|---|---|
401 / SERVICE KEY ERROR |
ν€ νμ±ν μ / λ§λ£ / λ³΅μ¬ μ 곡백 ν¬ν¨ | λ°κΈ μ§νλΌλ©΄ 30λΆ~1μκ° λκΈ° ν μ¬μλ. λ§λ£μΌμ νμΈ. ν€ μλ€ κ³΅λ°±Β·λ°μ΄ν μ κ±° ν μ¬μ λ ₯ |
403 / ACCESS_DENIED |
IP λΆμΌμΉ (κ°μ₯ νν¨) | curl -s https://api.ipify.org κ²°κ³Όμ λ§μ΄νμ΄μ§ λ±λ‘ IP λΉκ΅. λΆμΌμΉλ©΄ λͺ©λ‘ λ³κ²½μ μ² μΌλ‘ IP μμ . μμ£Ό λ°λλ€λ©΄ *.*.*.* λ‘ κ°±μ |
μλ΅μ΄ λΉμμ / body [] |
μ μ β μ΅κ·Ό μ¬λλ¬Έμκ° μλ μκ°λ | μ‘°μ©ν μκ°μλ λΉ μλ΅μ΄ μ μ. ν° μ¬λΒ·κΈ°μνΉλ³΄ μ μ±μμ§ |
μΈ λ°μ΄ν°μ
λͺ¨λ data.go.kr μ΄μκΈ°κ΄ κΈ°μμ² (1360000). μΈμ¦ν€λ λ΄ κ³μ μ νλμ ν€λ₯Ό κ·Έλλ‘ μ¬μ©νμ§λ§, νμ©μ μ²μ κ°κ° λ°λ‘ ν΄μΌ ν©λλ€.
| μλΉμ€ | λ°λ‘ κ²μ | κ²μμ΄ | endpoint |
|---|---|---|---|
| πͺοΈ κΈ°μνΉλ³΄ | π κΈ°μνΉλ³΄ κ²μ | κΈ°μνΉλ³΄ |
1360000/WthrWrnInfoService |
| π μ§μ§μ 보 | π μ§μ§μ 보 κ²μ | μ§μ§μ 보 |
1360000/EqkInfoService |
| β λ¨κΈ°μ보 | π λ¨κΈ°μ보 κ²μ | λ¨κΈ°μ보 |
1360000/VilageFcstInfoService_2.0 |
data.go.kr μ΄μκΈ°κ΄ νκ΅νκ²½κ³΅λ¨ (B552584) μ λ°μ΄ν°μ
2건μ κ°κ° νμ©μ μ²ν΄μΌ ν©λλ€.
| λ°μ΄ν°μ | λ°λ‘ κ²μ | κ²μμ΄ | endpoint |
|---|---|---|---|
| μΈ‘μ μμ 보 | π μΈ‘μ μμ 보 | μμ΄μ½λ¦¬μ μΈ‘μ μ |
B552584/MsrstnInfoInqireSvc |
| λκΈ°μ€μΌμ 보 | π λκΈ°μ€μΌμ 보 | μμ΄μ½λ¦¬μ λκΈ°μ€μΌ |
B552584/ArpltnInforInqireSvc |
π‘ μΈ‘μ μμ 보 λΉ μ§λ©΄ HA μ€μ νλ©΄μ μΈ‘μ μ dropdownμ΄ λΉμ΄ 보μ λλ€.
β οΈ μ΅μ β μνκΈ°μμ§μ (UVΒ·λκΈ°μ 체): μ¬μ©νλ €λ©΄ μΆκ°λ‘μνκΈ°μμ§μκ²μ β κΈ°μμ² λ°μ΄ν°μ νμ©μ μ². λ¨ μ½λλ V4 endpoint νΈμΆμ΄μ§λ§ ν¬νΈμ V5λ‘ μ κ·Έλ μ΄λλ μνλ‘ λ³΄μ λλ€ β μ€μ λμ λ―Έκ²μ¦. λ±λ‘ ν HA λ‘κ·Έ(LivingWthrIdxκ²μ)λ‘ νμΈνμΈμ. λ―Έμλ μ issue λΆνλ립λλ€.
| νλͺ© | κ° |
|---|---|
| π ν¬νΈ | π Opinet μ€νΌλ· API μ μ² νμ΄μ§ |
| λ°κΈ μ μ°¨ | λ¬΄λ£ νμκ°μ β API μ μ² β μ¦μ λ°κΈ |
| μ½λ νΈμΆ endpoint | opinet.co.kr/api/avgAllPrice.do, lowTop10.do |
π‘ Opinetμ 곡곡λ°μ΄ν°ν¬νΈκ³Ό λ³κ° ν¬νΈμ λλ€.
| νλͺ© | κ° |
|---|---|
| π ν¬νΈ | π NEIS κ΅μ‘μ 보 κ°λ°© ν¬νΈ |
| λ°κΈ μ μ°¨ | νμκ°μ β μΈμ¦ν€ μ μ² β λ§μ΄νμ΄μ§ "μ μ²νν©" μμ νμΈ |
| μ½λ νΈμΆ endpoint | open.neis.go.kr/hub/... |
π‘ NEISλ 곡곡λ°μ΄ν°ν¬νΈκ³Ό λ³κ° ν¬νΈμ λλ€. νκ΅λͺ μ HA μ€μ μμ μλ κ²μλ©λλ€ (νκ΅λͺ λ§ μ λ ₯νλ©΄ dropdown νμ).
β λΌμ΄λΈ κ²μ¦ μλ£ (2026-05-18): νκ΅ λ²μ€λ‘ μμΈ μ λλ¦Όλ.ꡬλ‘μ(μ€)(ARS 17003) + κ²½κΈ° μν₯ μκ³μ°λ―Έλ¦°λνΌμ€νΈ(ARS 25842) λ μ λ₯μ₯ λμ λ±λ‘ β λ Έμ λΉ λμ°© sensor + μλ‘κ³ μΉ¨ λ²νΌ + νμ±ν μ€μμΉ μ μ λμ. λμ°©μκ° / μ°¨λλ²νΈ / νμ¬μ λ₯μ₯ / λ Έμ 첫차·λ§μ°¨Β·λ°°μ°¨κ°κ²© λͺ¨λ attribute λΌμ΄λΈ μλ΅ νμΈ.
λ²μ€/μ§νμ² κ΄λ ¨ν΄ λ©λ΄μ μΈ κ°μ§ νλͺ©μ΄ 보μ λλ€. μλ리μ€λ³ μ 리:
| λ©λ΄ | λ°μ΄ν° μμ€ | API ν€ | νΉμ§ | μΆμ² μ¬μ©μ |
|---|---|---|---|---|
| π λμ€κ΅ν΅ (μ§νμ² / λ²μ€) | μμΈ μ΄λ¦°λ°μ΄ν°κ΄μ₯ (μ§νμ² ) + μΉ΄μΉ΄μ€λ§΅ (λ²μ€) | μ§νμ² μ β , λ²μ€λ β | ν ν΅ν©μ μ§νμ² μ + λ²μ€μ λ₯μ₯ νΌν© λ±λ‘. νμΉκ²½λ‘ μ΅μ ν€λ μ§μ | μ§νμ² Β·λ²μ€ λͺ¨λ μ°λ μμΈ/μλκΆ μ¬μ©μ |
| π μμΈλ²μ€ (곡μ API) | μμΈνΉλ³μ μ λ₯μμ 보쑰ν API (ws.bus.go.kr) | β data.go.kr | 곡μ API κΈ°λ° κ°μ₯ μ ν. ARS-ID μ λ ₯ β μλμΌλ‘ λ Έμ λͺ©λ‘ μ‘°ν. μ λ₯μ₯λΉ μλ‘κ³ μΉ¨ λ²νΌ + μ΅μ μμ μ λ₯μ₯ μΆκ°/μ κ±°/λ Έμ νΈμ§ | μμΈλ§ λ€λκ³ κ³΅μ API μμ μ±μ μνλ μ¬μ©μ |
| π νκ΅ λ²μ€ (μ κ΅) | μΉ΄μΉ΄μ€λ§΅ λͺ¨λ°μΌ | β λΆνμ | μ λ₯μ₯ μ΄λ¦ κ²μ UI. μ κ΅ λλΆλΆ μ λ₯μ₯. μ΅μ μμ ν΄λ§ μ£ΌκΈ° λ³κ²½ (30s~1h) | ν€ λ°κΈμ΄ λΆλ΄μ€λ½κ±°λ, μμΈ μΈ μ§μ μ¬μ©μ |
μμΈλ²μ€ / νκ΅ λ²μ€ β 무μμ΄ λ€λ₯Έκ°?
- κ°μ μ λ₯μ₯μ΄λΌλ λ°μ΄ν° μμ€κ° λ€λ₯΄λ©΄ μλ΅μ΄ μ½κ° λ€λ₯Ό μ μμ΅λλ€ (μ: "κ³§ λμ°©" vs "1λΆ ν"). μμΈλ²μ€λ 곡μ APIλΌ κ°μ₯ μ ν, νκ΅ λ²μ€λ μΉ΄μΉ΄μ€λ§΅ λͺ¨λ°μΌ μ¬μ΄νΈλΌ μ¬μ΄νΈ κ°νΈ μ μΌμ κΉ¨μ§ μν.
- λ ν΅ν©μ λμμ λ±λ‘ν΄λ 무방 (μλ‘ λ 립). λΉκ΅μ©μΌλ‘ μ°μλ λΆλ μμ΅λλ€.
μΉ΄μΉ΄μ€λ§΅ μ λ₯μ₯ ID μ°Ύλ λ² ("λμ€κ΅ν΅" λ©λ΄μ λ²μ€ λ±λ‘ μ. "νκ΅ λ²μ€"λ μ΄λ¦ κ²μμ΄λΌ ID λΆνμ):
μΉ΄μΉ΄μ€λ§΅ β μ λ₯μ₯ κ²μ β μ λ₯μ₯ ν΄λ¦ β URL ?busstopid=03171&... β busstopid= λ€μ κ° λ³΅μ¬ (μ: 03171, BS09013700).
μμΈλ²μ€ ARS-ID μ°Ύλ λ² ("μμΈλ²μ€" λ©λ΄ λ±λ‘ μ):
bus.go.kr λλ μ λ₯μ₯ νμ§νμ μ ν 5μ리 μ λ₯μλ²νΈ (μ: 23288 = μ¬λΉμ).
| νλͺ© | κ° |
|---|---|
| π ν¬νΈ | 곡곡λ°μ΄ν°ν¬νΈ (data.go.kr) |
| π λ°λ‘ κ²μ | π μμΈνΉλ³μ_μ λ₯μμ 보쑰ν μλΉμ€ |
| μ΄μκΈ°κ΄ | μμΈνΉλ³μ |
| λ°μ΄ν°μ λͺ | μμΈνΉλ³μ_μ λ₯μμ 보쑰ν μλΉμ€ |
| μ½λ νΈμΆ endpoint | ws.bus.go.kr/api/rest/stationinfo/getStationByUid |
| μΌμΌ νΈμΆ νλ | 1,000ν (μΆ©λΆ β 1λΆ ν΄λ§μ΄λ©΄ 1,440/μΌ μ΄μ§λ§ νμ±ν μ€μμΉλ‘ μ μ΄) |
μ μ² λ¨κ³:
- data.go.kr νμκ°μ β μ "π λ°λ‘ κ²μ" λ§ν¬ ν΄λ¦
- μμΈ νμ΄μ§ β νμ©μ μ² λ²νΌ β νΌ μμ± (μλμΉμΈ datasetμ΄λΌ λ³λ IP λ±λ‘ λΆνμ)
- λ§μ΄νμ΄μ§ β μ€νAPI β μΈμ¦ν€ λ°κΈνν© β μΌλ° μΈμ¦ν€ κ° λ³΅μ¬
β οΈ μ€μ β ν€ νμ±νμ μ½ 24μκ° μμλ©λλ€.λ§μ΄νμ΄μ§μ "μ²λ¦¬μν: μΉμΈ" + "νμ©κΈ°κ°: μ€λλΆν°" λ‘ νμλμ΄λ, μ€μ API gateway μ μΈμ¦λͺ¨λμ ν€κ° λ±λ‘λκΈ°κΉμ§ μ½ 24μκ° μΆκ° λκΈ°κ° νμν©λλ€. λ°κΈ μ§ν HA ν΅ν© μΆκ° μ "API ν€κ° μ ν¨νμ§ μμ΅λλ€" λ©μμ§κ° λμλ μ μμ΄λ©°, λ€μλ κ°μ μκ° μ¬μλνμλ©΄ λ©λλ€.
24μκ° νμλ κ°μ μλ¬λ©΄:
- νμ©μ μ² λ°μ΄ν°μ μ΄λ¦μ΄ μ νν "μμΈνΉλ³μ_μ λ₯μμ 보쑰ν μλΉμ€" μΈμ§ μ¬νμΈ (λΉμ·ν μ΄λ¦μ λ€λ₯Έ datasetμ΄ μμ)
- data.go.kr κ³ κ°μΌν° 1566-0025 λ¬Έμ
- λλ λ§μ΄νμ΄μ§μμ νμ©μ μ² ν΄μ β μ¬μ μ²
λ ν΅ν© λͺ¨λ μ λ₯μ₯λ§λ€ switch.<flow>_<id>_update_active μ€μμΉκ° μλ μμ±λ©λλ€. ON μΌ λλ§ APIλ₯Ό νΈμΆνκ³ , OFF μΌ λλ μ§μ λ°μ΄ν°λ₯Ό κ·Έλλ‘ μ μ§νλ©΄μ νΈμΆμ 건λλλλ€.
μ μ΄κ² μ μ©νκ°?
- API νΈμΆ νλ μ κ° (νΉν μμΈλ²μ€ 1,000/μΌ νλ)
- μλ²½ λλ μΈμΆ μ€μΌ λ κ΅³μ΄ ν΄λ§ μ ν¨
- HA μλνλ‘ "νμν λλ§" μ λ° μ μ΄
default λμ:
- μ κ· μ€μΉ β ON μΌλ‘ μμ (λ°μ΄ν° μ¦μ 보μ)
- μ¬μμ μ β λ§μ§λ§ ON/OFF μν μλ 볡μ
μλν μμ β μΆν΄κ·Ό μκ° + 거리 μ‘°κ±΄λ§ ν΄λ§:
alias: μΆν΄κ·Ό λ²μ€ λμ°©μ 보 ν΄λ§ μ μ΄
mode: restart
triggers:
- at: "06:30:00" # μΆκ·Ό μκ°
id: morning_on_time
trigger: time
- entity_id: sensor.<μ§-μ λ₯μ₯-거리> # 거리 sensor (proximity λλ template)
above: 1000
id: morning_off_dist
trigger: numeric_state
- at: "17:30:00" # ν΄κ·Ό μκ°
id: evening_on_time
trigger: time
- entity_id: sensor.<μ§-μ λ₯μ₯-거리>
below: 200
id: evening_off_dist
trigger: numeric_state
actions:
- choose:
# μΆκ·Όμκ° + νμΌ + μ§ κ·Όμ² β ON
- conditions:
- condition: trigger
id: morning_on_time
- condition: state
entity_id: binary_sensor.workday_sensor
state: "on"
- condition: numeric_state
entity_id: sensor.<μ§-μ λ₯μ₯-거리>
below: 200
sequence:
- service: switch.turn_on
target:
entity_id: switch.seoul_bus_*****_update_active
# μΆκ·Ό ν λ©μ΄μ§λ©΄ β OFF
- conditions:
- condition: trigger
id: morning_off_dist
sequence:
- service: switch.turn_off
target:
entity_id: switch.seoul_bus_*****_update_active
# ν΄κ·Όμκ° + νμ¬ κ·Όμ² β ON
- conditions:
- condition: trigger
id: evening_on_time
sequence:
- service: switch.turn_on
target:
entity_id: switch.seoul_bus_*****_update_active
# μ§ λμ°© β OFF
- conditions:
- condition: trigger
id: evening_off_dist
sequence:
- service: switch.turn_off
target:
entity_id: switch.seoul_bus_*****_update_activeβ νμμ API νΈμΆ 0ν, μΆκ·Ό/ν΄κ·Ό μκ°μλ§ ν΄λ§.
λμ보λ μ‘°κ±΄λΆ νμ (HACS state-switch μΉ΄λ μΆμ²):
type: custom:state-switch
entity: switch.seoul_bus_*****_update_active
states:
on:
type: entities
entities:
- sensor.seoul_bus_*****_*****_now
- sensor.seoul_bus_*****_*****_next
- button.seoul_bus_*****_refresh
off:
type: custom:button-card
color_type: blank-card # μ€μμΉ OFFλ©΄ μΉ΄λ μ체 μ 보μν΅ν© μΆκ° ν μ λ₯μ₯μ λ μΆκ°νκ±°λ λ Έμ μ νΈμ§νλ €λ©΄ μμ Β·μ¬λ±λ‘ νμ μμ΅λλ€:
μ€μ β κΈ°κΈ° λ° μλΉμ€ β "νκ΅ μ»΄ν¬λνΈ ν€νΈ" μΉ΄λ β "ꡬμ±" λ²νΌ β λ©λ΄ λ±μ₯:
| λ©λ΄ | λμ |
|---|---|
| π μ λ₯μ₯ μΆκ° | μ μ λ₯μ₯ λ±λ‘ (μμΈ: ARS-ID μ λ ₯ / νκ΅ λ²μ€: μ΄λ¦ κ²μ) |
| π μ λ₯μ₯ μμ | 볡μ μ ν κ°λ₯ |
| π μ λ₯μ₯ λ Έμ νΈμ§ | κΈ°μ‘΄ μ λ₯μ₯μμ μΆμ ν λ Έμ λ³κ²½ |
| π API ν€ λ³κ²½ (μμΈλ²μ€λ§) | μ ν€ μ λ ₯ μ μ μ₯ μ§μ μλ κ²μ¦ |
| β± ν΄λ§ μ£ΌκΈ° λ³κ²½ (νκ΅ λ²μ€λ§) | 30μ΄ ~ 1μκ° |
| β μ μ₯ ν μ’ λ£ | λ³κ²½ μ¬ν μΌκ΄ μ μ₯ + μλ reload |
X λ«κΈ° μ λ³κ²½ μ¬ν λ¬΄ν¨ (transactional ν¨ν΄).
| λΈλ£¨νλ¦°νΈ | π μμΈλ²μ€ | π νκ΅ λ²μ€ |
|---|---|---|
| μΆλ° μλ | β | β |
| νμ°¨ μλ | β | β |
| λ§μ°¨ μλ | β | β |
| λ§μ°¨ / νΌμ‘ μλ | β | β (μΉ΄μΉ΄μ€λ§΅ μλ΅μ λ§μ°¨ νλ μμ) |
| μ λ₯μ₯ κ·Όμ² μλ νμ±ν (μμΉ κΈ°λ°) | β | β |
| μ§ λ λ λ μλ¦Ό (μμΉ κΈ°λ°) | β | β |
| λͺ©μ μ§ λμ°© νμ°¨ μλ (μμΉ κΈ°λ°) | β | β |
| μΆν΄κ·Ό μλ λͺ¨λ (μμΉ κΈ°λ°) | β | β |
β 8κ° μ€ 7κ°κ° μμͺ½ λͺ¨λ λμ. νκ΅ λ²μ€ μ¬μ©μλ 95%μ μλν κ°μΉλ₯Ό κ·Έλλ‘ λ릴 μ μμ΅λλ€.
λͺ¨λ λΈλ£¨νλ¦°νΈμ "μλ¦Ό μ‘μ " μ λ ₯μ HA action selector μ λλ€. import μ UIμμ:
- service λλ‘λ€μ΄μμ
notify.mobile_app_my_phoneκ°μ΄ λ³ΈμΈμ notify μλΉμ€ μ ν - title / message λ default λ‘
{{ alert_title }}/{{ alert_message }}template κ° λ€μ΄κ° μμ΄μ β λΈλ£¨νλ¦°νΈ λ΄λΆ λ³μκ° μμμ μ±μ μ€λλ€ - μνμλ©΄ λ€λ₯Έ μλ¦Ό μλΉμ€(μ:
notify.telegram,media_player.tts.google_sayλ±)λ‘λ μμ λ‘κ² λ³κ²½ κ°λ₯
곡곡λ°μ΄ν° νμ©μ¬λ‘ λΉλμ ν¨ν΄λ€μ HA λΈλ£¨νλ¦°νΈ λ‘ μ 곡ν©λλ€.
| λΈλ£¨νλ¦°νΈ | νΈλ¦¬κ±° | μ©λ |
|---|---|---|
| π μΆλ° μλ | native_value (TIMESTAMP) κ° NλΆ μ΄λ΄ μ§μ
|
μ λ₯μ₯κΉμ§ λ보 NλΆ β "μ§κΈ μΆλ°νμΈμ" νΈμ |
| π νμ°¨ μλ | sensor μ current_stop attribute κ° λ³κ²½ |
νμΉ μ€ μ§μ μ λ₯μ₯ Nκ° μ λλ¬ μ νΈμ ("λ΄λ¦΄ μ κ±°μ₯μ λλ€") |
| π λ§μ°¨ μλ | last_vehicle / is_last attribute |
λ§μ°¨ μ΄ν μ νΈμ ("μ΄λ² μ°¨κ° λ§μ°¨μ λλ€") |
| π¨ λ§μ°¨ / νΌμ‘ μλ | λ§μ°¨ binary_sensor ON + congestion λ³ν |
λ§μ°¨ μ λ€μ μ°¨ λμ°©μκ° νΈμ (μμΈλ²μ€ μ μ©) |
Import λ°©λ² (UI ν λ²μ):
- HA β μ€μ β μλν β λΈλ£¨νλ¦°νΈ β λΈλ£¨νλ¦°νΈ κ°μ Έμ€κΈ°
- μλ URL μ€ μνλ μλν URL λΆμ¬λ£κΈ° β 미리보기 β λΈλ£¨νλ¦°νΈ κ°μ Έμ€κΈ°
μΆλ° μλ: https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/bus_departure_alert.yaml
νμ°¨ μλ: https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/bus_alight_alert.yaml
λ§μ°¨ μλ: https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/bus_lastride_alert.yaml
λ§μ°¨/νΌμ‘ μλ: https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/bus_crowded_alert.yaml
- μλν λ§λ€κΈ° β λΈλ£¨νλ¦°νΈ μ ν β sensor + λλ°μ΄μ€ + λΆ λ± μ λ ₯ β μ μ₯
π‘ λͺ¨λ°μΌ νΈμλ HA Companion App (iOS / Android) κ° μ€μΉλ λλ°μ΄μ€μ
notify.mobile_app_<ν°_μ΄λ¦>μλΉμ€λ₯Ό μ¬μ©ν©λλ€. ν° μ΄λ¦μ μ€μ β λλ°μ΄μ€ β Companion App λ±λ‘ μ νμλ μ΄λ¦.
νμ©μ¬λ‘:
- π μΌκ° μΈμΆ ν λ§μ°¨ μλ β λμΉλ©΄ νμ
- π μΆν΄κ·Ό μ λ§μ°¨ μλ β λ€μ μ°¨ κΈ°λ€λ¦¬κ±°λ λ€λ₯Έ λ Έμ μ΄μ©
- π μΆκ·Ό μ μΆλ° μλ β μ λ₯μ₯κΉμ§ λ보 + μ νΈ λκΈ° κ³ λ €ν΄μ μλ 5λΆ μ
HA Companion App μΌλ‘ μΆμ λλ λ³ΈμΈ ν°μ device_tracker μμΉλ₯Ό νμ©ν μλν. μΌλ° λ²μ€μ±μ΄ λͺ» νλ HA + ν° μμΉμ κ°μ .
| λΈλ£¨νλ¦°νΈ | λμ |
|---|---|
| π μ λ₯μ₯ κ·Όμ² μλ νμ±ν | ν°μ΄ μ λ₯μ₯ zone μ§μ β νμ±ν μ€μμΉ ON, λ λλ©΄ NλΆ ν OFF |
| π μ§ λ λ λ λ²μ€ μκ° μλ¦Ό | zone.home λ λλ μκ° λ€μ λ²μ€ λμ°© μκ° νΈμ |
| π λͺ©μ μ§ λμ°© μ νμ°¨ μλ | ν°μ΄ λͺ©μ μ§ zone μ§μ β νΈμ ("λ΄λ¦΄ μ κ±°μ₯ λμ°©") β λ²μ€μμ μ λ€μ΄λ μμΉλ‘ κΉ¨μ |
| π μΆν΄κ·Ό μλ λͺ¨λ | μκ° + μμΉ β νμ±ν μ€μμΉ μλ ON/OFF (μλ³Έ κ°λ°μ μλν ν¨ν΄) |
μ ν λ¨κ³ β μ λ₯μ₯ / νμ¬ zone λ§λ€κΈ°:
- HA β μ€μ β μμ(Zone) β μΆκ°
- μ λ₯μ₯ μ’ν μ λ ₯ (μΉ΄μΉ΄μ€λ§΅ β μ λ₯μ₯ ν΄λ¦ β μκ²½λ νμΈ)
- λ°κ²½: μ λ₯μ₯ zoneμ 100~200m, νμ¬/νκ΅ zoneμ 200~300m κΆμ₯
Import URL:
μ λ₯μ₯ κ·Όμ² μλ νμ±ν: https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/stop_proximity_toggle.yaml
μ§ λ λ λ λ²μ€ μλ¦Ό: https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/leaving_home_alert.yaml
λͺ©μ μ§ λμ°© νμ°¨ μλ: https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/arrival_alight_alert.yaml
μΆν΄κ·Ό μλ λͺ¨λ: https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/commute_auto_mode.yaml
μμΉ κΈ°λ° μλν μ‘°ν© μμ:
- "μ λ₯μ₯ κ·Όμ² μλ νμ±ν" + "μ§ λ λ λ μλ¦Ό" = μΈμΆ μ μμμ ν΄λ§ + λ€μ λ²μ€ μλ΄
- "λͺ©μ μ§ λμ°© νμ°¨ μλ" = λ²μ€μμ μ λ€μ΄λ μμ
- "μΆν΄κ·Ό μλ λͺ¨λ" = νμΌ μΆν΄κ·Όλ§ μ νν ν΄λ§, μ£Όλ§/μΈμΆ μ μλ OFF (API νΈμΆ νλ μ κ°)
μ€μ β κΈ°κΈ° λ° μλΉμ€ β + ν΅ν© ꡬμ±μμ μΆκ° β νκ΅ μ»΄ν¬λνΈ ν€νΈ κ²μ β μνλ μλΉμ€ μ ν.
ν ν΅ν©μ 13κ° μλΉμ€κ° λ©λ΄λ‘ λ€μ΄μμ΄, μΆκ°νλ €λ μλΉμ€λ§λ€ ν λ²μ© λ±λ‘ν©λλ€. κ°μ μλΉμ€λ₯Ό μ¬λ¬ μ§μμΌλ‘ μ€λ³΅ λ±λ‘λ κ°λ₯ (μ: μ½κ΅μ μν₯μΒ·μμμΒ·λΆλͺ¨λ λ μꡰꡬ 3λ² λ±λ‘).
ν΄λΉ νλͺ© μ "ꡬμ±" λ²νΌ β μ λ ₯κ° νΈμ§. (μμ Β·μ¬λ±λ‘ μμ΄ κ°λ₯. entityμ μλν μ°κ²° μ μ§λ¨.)
| μλΉμ€ | μ΄λμ λ°λκ° |
|---|---|
| β‘ KEPCO | νμ ννμ΄μ§ ID/λΉλ°λ²νΈ (λ³ΈμΈ κ³μ , 2μ°¨ μΈμ¦ λ―Έμ§μ) |
| π§ μ리μ | μ’ μ΄ κ³ μ§μ λλ μ리μ μ¬μ΄λ² κ³ κ°μΌν° β μκΈμ‘°ν μ’μΈ‘ μμ©κ°λ²νΈ + κ³ κ°λͺ |
| π κ°μ€μ± | μ¬μ©κ³μ½λ²νΈλ κ°μ€μ± λͺ¨λ°μΌ μ± β λ΄ μ 보. ν ν°Β·νμIDλ mitmproxy λ±μΌλ‘ λͺ¨λ°μΌ μ± HTTPS μμ²μ X-Token/X-Member ν€λ μΆμΆ ( |
| π μ§μ§ μ’ν | κΈ°λ³Έκ°μ μμΈμμ² (37.5665, 126.978). λ³ΈμΈ μ§ μ’νλ‘ κΌ λ³κ²½. κΈ°λ³Έ λ°κ²½ 200km / μ΅μ κ·λͺ¨ 3.0 |
entity_idλ νκ΅μ΄ β λ‘λ§μ μ¬λ¬κ·Έ μλ λ³ν (μ:
μ½κ΅ - μν₯μ+μ΄μ μ½κ΅ μβsensor.yaggug_siheungsi_unyeong_yaggug_su). μ νν IDλ κ°λ°μ λꡬ β μν μμ μΉν μ΄λ¦μΌλ‘ κ²μν΄ νμΈ.
| μλΉμ€ | μΉν μ΄λ¦ (sensor λ±) | μ£Όμ attribute |
|---|---|---|
| π μ½κ΅ | μ΄μ μ½κ΅ μ |
pharmacies[] (μ΅λ 50: nameΒ·addressΒ·phoneΒ·latΒ·lonΒ·today_hoursΒ·open_nowΒ·duty_time), total, shown, open_now_count |
| π¨ μμ μλ¦Ό | μ΅μ μμ μλ¦Ό, μμ μλ¦Ό μ, μ€λ μμ μλ¦Ό μ¬λΆ (binary), μμ μλ¦Ό μ΄λ²€νΈ (event) |
latest, alerts[], count |
| π’ μ¬λλ¬Έμ | μ΅μ μ¬λλ¬Έμ, μ¬λλ¬Έμ μ, μ¬λλ¬Έμ μ΄λ²€νΈ (event) |
level, area, disaster_type |
| πͺοΈ κΈ°μνΉλ³΄ | νΈμ° νΉλ³΄/κ°ν νΉλ³΄/νν νΉλ³΄/... (event 12μ’
) |
state: advisory/warning/pre_*/cancelled/none, start_time, end_time |
| π μ§μ§ | μ§μ§ 경보 (event) |
magnitude, location, distance_km, datetime |
| β λλ€μ보 | (weather μν°ν° 1κ° β HA κΈ°λ³Έ Weather μΉ΄λ νΈν) | hourly/daily forecast μλΉμ€ μ§μ |
| π«οΈ μμ΄μ½λ¦¬μ | PM10 λ―ΈμΈλ¨Όμ§, PM2.5 μ΄λ―ΈμΈλ¨Όμ§, Oβ μ€μ‘΄, NOβ μ΄μ°νμ§μ, SOβ μν©μ°κ°μ€, CO μΌμ°ννμ, ν΅ν©λκΈ°μ§μ§μ + binary λκΈ°μ§ κ²½λ³΄ + event + calendar λκΈ°μ§ μ보 |
λ±κΈ(Grade) λλ° |
| β‘ KEPCO | νμ¬ μ¬μ©λ (kWh), μ§λλ¬ μκΈ (μ), μμ μκΈ (μ), κ³ κ°λ²νΈ, μ λ ₯κ΅¬λΆ |
β |
| π§ μ리μ | μλ μκΈ (μ), μ¬μ©λ (γ₯), μ²κ΅¬μ |
billing_month, customer_info, arrears_info |
| π κ°μ€μ± | μ²κ΅¬ μ λͺ©, μ΄ μκΈ (μ) |
β |
| β½ μ κ° | μ κ΅ νκ· κ°, μ΅μ κ° (λ±λ‘ν μλΓμ μ’
μ‘°ν©λ§λ€) |
ranking[] (Top 5 μ£Όμ μ μ΄λ¦Β·κ°κ²©Β·μ£Όμ) |
| π« νκ΅ | κΈμ, νκ΅ μ 보 + calendar νμ¬μΌμ /μκ°ν |
κΈμ: menu, calorie, allergy_codes |
| π λμ€κ΅ν΅ | <μ/μ λ₯μ₯> ... λμ°© (TIMESTAMP β HAκ° "NλΆ ν"λ‘ μλ νμ) |
β |
| π μμΈλ²μ€ | λ
Έμ λΉ: λμ°© sensor 2κ° (λ€μ/λ€λ€μ, TIMESTAMP) + μ μλ²μ€ binary_sensor + λ§μ°¨ binary_sensor. μ λ₯μ₯λΉ: μλ‘κ³ μΉ¨ λ²νΌ + μ
λ°μ΄νΈ νμ±ν μ€μμΉ |
vehicle_no, current_stop, message, is_full, is_low_floor, bus_type (μΌλ°/μ μ/κ΅΄μ ), congestion (μ¬μ /보ν΅/νΌμ‘), passengers_aboard, remaining_seats, direction, status |
| π νκ΅ λ²μ€ | λ Έμ λΉ: λμ°© sensor 2κ°. μ λ₯μ₯λΉ: μλ‘κ³ μΉ¨ λ²νΌ + μ λ°μ΄νΈ νμ±ν μ€μμΉ | vehicle_number, current_stop, message, remain_seat, next_stop, first_time/last_time/intervals, bus_type, status |
κ²μΒ·νν° ν¬νΌ λ κ° λ¨Όμ :
- μ€μ β ν¬νΌ β ν
μ€νΈ:
input_text.yaggug_geomsaeg("μ½κ΅ κ²μ") - μ€μ β ν¬νΌ β ν κΈ:
input_boolean.yaggug_yeongeobjungman("μ½κ΅ μμ μ€λ§")
λμ보λ YAML (μΉμ /vertical-stackμ ν΅μ§Έλ‘ λΆμ¬λ£κΈ°. λ³ΈμΈ μ½κ΅ entity_idλ‘ λ³κ²½):
type: vertical-stack
cards:
- type: heading
heading: π μ΄μ μ½κ΅
heading_style: title
icon: mdi:pharmacy
- type: horizontal-stack
cards:
- type: tile
entity: sensor.yaggug_siheungsi_unyeong_yaggug_su # λ³ΈμΈ entity_id
name: μ 체 μ½κ΅
icon: mdi:pharmacy-marker
color: green
- type: tile
entity: sensor.yaggug_siheungsi_unyeong_yaggug_su
name: μ§κΈ μμ
μ€
icon: mdi:clock-check
color: blue
state_content: open_now_count
- type: entities
title: κ²μ / νν°
show_header_toggle: false
entities:
- entity: input_text.yaggug_geomsaeg
name: π μ΄λ¦ κ²μ
- entity: input_boolean.yaggug_yeongeobjungman
name: π’ μ§κΈ μμ
μ€λ§
- type: markdown
title: μ½κ΅ λͺ©λ‘ (κ°κΉμ΄ μ)
content: |
{% set tracker = 'zone.home' %}
{% set sensor_id = 'sensor.yaggug_siheungsi_unyeong_yaggug_su' %}
{% set my_lat = state_attr(tracker, 'latitude') | float(0) %}
{% set my_lon = state_attr(tracker, 'longitude') | float(0) %}
{% set ph = state_attr(sensor_id, 'pharmacies') or [] %}
{% set raw_query = states('input_text.yaggug_geomsaeg') | default('', true) %}
{% set query = '' if raw_query in ['unknown', 'unavailable', 'none', None] else raw_query | lower | trim %}
{% set open_only = is_state('input_boolean.yaggug_yeongeobjungman', 'on') %}
{% set step1 = ph if not query else ph | selectattr('name', 'search', query) | list %}
{% set filtered = step1 | selectattr('open_now') | list if open_only else step1 %}
{% set ns = namespace(items=[]) %}
{% for p in filtered %}
{% set d = distance(my_lat, my_lon, p.lat | float(0), p.lon | float(0)) %}
{% set ns.items = ns.items + [(d, p)] %}
{% endfor %}
{% set ranked = ns.items | sort %}
**νμ {{ ranked | length }}κ³³** Β· κΈ°μ€ `{{ tracker }}`
{% if query %}Β· κ²μ `{{ query }}`{% endif %}{% if open_only %}Β· μμ
μ€λ§{% endif %}
---
{% for d, p in ranked[:15] %}
{% set dist_label = ((d * 1000) | round(0) | int | string) + 'm' if d < 1 else ((d | round(1) | string) + 'km') %}
### {{ 'π’' if p.open_now else 'βͺ' }} {{ p.name }} Β· _{{ dist_label }}_
- π {{ p.address }}
- π [{{ p.phone or 'λ²νΈ μμ' }}](tel:{{ (p.phone or '') | replace('-','') }})
- π {{ ('μ§κΈ μμ
μ€ (' + p.today_hours + ')') if p.open_now else (('μ€λ ' + p.today_hours) if p.today_hours else 'μ€λ ν΄λ¬΄') }}
- πΊοΈ [μΉ΄μΉ΄μ€λ§΅](https://map.kakao.com/link/map/{{ p.name | urlencode }},{{ p.lat }},{{ p.lon }}) Β· [κΈΈμ°ΎκΈ°](https://map.kakao.com/link/to/{{ p.name | urlencode }},{{ p.lat }},{{ p.lon }})
{% endfor %}π‘ μμΉ κΈ°μ€μ ν° λ°λΌκ°κ² νλ €λ©΄
tracker = 'zone.home'μperson.<λ³ΈμΈ>λλdevice_tracker.<ν°>μΌλ‘ λ³κ²½.
HAμ Assist + LLM ν΅ν© (OpenAI / Google / Ollama λ±)μ λ³Έ μ»΄ν¬λνΈλ₯Ό λ ΈμΆνλ©΄ νκ΅μ΄λ‘ μ§μ λ¬Όμ μ μμ΅λλ€.
| μ§λ¬Έ | λ§€μΉ μλΉμ€ |
|---|---|
| "μ§κΈ μμ μ€μΈ κ°κΉμ΄ μ½κ΅ μλ €μ€" | π μ½κ΅ |
| "μ€λ λ―ΈμΈλ¨Όμ§ μ΄λ?" | π«οΈ μμ΄μ½λ¦¬μ |
| "λ΄μΌ λΉ μ?" | β κΈ°μμ² |
| "μ΅κ·Ό μ¬λλ¬Έμ λ μμ΄?" | π’ μ¬λλ¬Έμ |
| "μ€λ κΈμ λμΌ?" | π« νκ΅ |
| "λ€μ λ²μ€ μΈμ μ?" | π λμ€κ΅ν΅ |
LLMμ λ ΈμΆ μ ν΄λ μΌλ° sensor/event/weather μν°ν°λ‘ μ μ λμ. μΆκ° μ€μ λΆνμ.
13κ°μ§λ₯Ό μ λΆ λ±λ‘ν΄μΌ νλμ?
μλμ. μνλ κ²λ§ λ±λ‘νμλ©΄ λ©λλ€. λ±λ‘ μ ν μλΉμ€λ entity·리μμ€λ₯Ό μ ν μ°μ§ μμ΅λλ€.
μ¬μ©λ£κ° λλμ?
μ λΆ λ¬΄λ£. μ λΆΒ·κ³΅κ³΅κΈ°κ΄ OpenAPIλ₯Ό μ¬μ©νλ©° λ³Έ μ»΄ν¬λνΈλ κ²°μ Β·κ³ΌκΈ μμ. κ° APIλ μΌμΌ νΈμΆ νλ(λ³΄ν΅ 1λ§~100λ§ν/μΌ)κ° μμ§λ§ κ°μ μ© 1μΈ μ¬μ©μΌλ‘ λκΈ°λ μΌμ κ±°μ μμ΅λλ€.
API ν€ μ μ²μ΄ λΆλ΄μ€λ¬μμ
ν€ μμ΄ λ°λ‘ λλ μλΉμ€ 4κ°μ§λΆν° 체ννμΈμ:
- π¨ μμ μλ¦Ό β μ§μλ§ μ ν (νμλΆ νμ΄μ§ μ€ν¬λν)
- β‘ νκ΅μ λ ₯ / π§ μ리μ / π κ°μ€μ± β λ³ΈμΈ κ³μ /λ²νΈλ‘ λ‘κ·ΈμΈ (API ν€ μλ)
μμΈ μΈ κ±°μ£Όμλ κ°λ₯νκ°μ?
λλΆλΆ μ κ΅ κ°λ₯. μμΈ μ μ©: μ리μ(μμλ), μμΈ μ§νμ² μ€μκ° λμ°©μ 보. λλ¨Έμ§λ μ κ΅ OK.
λ±λ‘ν API ν€Β·μ§μμ λ°κΎΈλ €λ©΄?
μ€μ β κΈ°κΈ° λ° μλΉμ€ β "νκ΅ μ»΄ν¬λνΈ ν€νΈ" μΉ΄λ β ν΄λΉ νλͺ©μ "ꡬμ±" λ²νΌ. μμ Β·μ¬λ±λ‘ μμ΄ entityμ μλν μ°κ²° μ μ§λ¨.
κ°μ μλΉμ€λ₯Ό μ¬λ¬ μ§μμΌλ‘ λ±λ‘ κ°λ₯?
κ°λ₯ν©λλ€. μ½κ΅ μλΉμ€λ₯Ό μν₯μΒ·μμμΒ·λΆλͺ¨λ λ 3λ² λ±λ‘νλ©΄ λ 립μ μΈ κΈ°κΈ°Β·entity 3μΈνΈκ° λ§λ€μ΄μ§λλ€.
νΈλν° μλ¦Όκ³Ό ν¨κ» μ°λ €λ©΄?
HA Automation + Companion μ± νΈμ μ‘°ν©. κ°μ₯ λ¨μν μμ:
automation:
- alias: "μ¬λλ¬Έμ β νΈλν° νΈμ"
trigger:
- platform: state
entity_id: sensor.<μ¬λλ¬Έμ_μ΅μ _μν°ν°_id> # κ°λ°μ λꡬμμ νμΈ
condition:
- condition: template
value_template: "{{ trigger.to_state.state not in ['μμ', 'unknown', 'unavailable'] }}"
action:
- service: notify.mobile_app_<ν°_μ΄λ¦>
data:
title: "π¨ μ¬λλ¬Έμ"
message: "{{ trigger.to_state.state }}"μ λ ₯ν λΉλ°λ²νΈΒ·ν€λ μ΄λ μ μ₯λλμ?
Home Assistant λ΄λΆ μ μ₯μ (.storage/) μλ§ μ μ₯λλ©° μΈλΆλ‘ μ μ‘λμ§ μμ΅λλ€. μ
λ ₯ν λΉλ°λ²νΈλ API νΈμΆ μ ν΄λΉ μλΉμ€(νμ Β·μ리μ λ±)μ 곡μ νμ΄μ§μλ§ μ¬μ©λ©λλ€.
μ λ°μ΄νΈλ μ΄λ»κ² λ°λμ?
HACSλ‘ μ€μΉνμ ¨λ€λ©΄ μ λ¦΄λ¦¬μ¦ μ HACS β ν΅ν© β KR Component Kit μ λΉ¨κ° μ νμ β UPDATE β HA μ¬μμ. κΈ°μ‘΄ μ€μ Β·entity μ μ§λ¨.
μ μΆ μννΈμΈλ° μꡰꡬ λͺ©λ‘μ λ΄ λμ΄ μμ΄μ
νμ ꡬμ μ½λκ° μ μΆ λκΉμ§ μ¦μ λ°μλμ§ μλ κ²½μ°κ° μμ΅λλ€. κ°μ₯ κ°κΉμ΄ μΈμ λ/ꡬλ₯Ό μ νν΄ μ£ΌμΈμ. κΈ°μμ² λλ€μ보λ 5kmΓ5km 격μλΌ μΈμ μ½λ μ νν΄λ μ€μ λ μ¨ κ±°μ λμΌ.
| μΉ΄ν κ³ λ¦¬ | μλΉμ€ | μ£ΌκΈ° |
|---|---|---|
| μ€μκ° | λ²μ€/μ§νμ² (λμ€κ΅ν΅ λ©λ΄) | 1~2λΆ |
| μ€μκ° | μμΈλ²μ€ / νκ΅ λ²μ€ | 1λΆ (μμΈλ²μ€ κ³ μ ) / 30s~1h μ‘°μ κ°λ₯ (νκ΅ λ²μ€) |
| μμ Β·μ¬λ | μ¬λλ¬Έμ, μμ μλ¦Ό, KEPCO | 5λΆ |
| μμ Β·μ¬λ | μ§μ§, κΈ°μνΉλ³΄ | 10~15λΆ |
| νκ²½/μ νΈ | κ°μ€μ±, κΈ°μμ² μ보, μμ΄μ½λ¦¬μ | 20~30λΆ |
| μν | μ리μ, μ½κ΅, μ κ° | 1μκ° |
| μν | νκ΅ (κΈμΒ·μκ°ν) | 6μκ° |
π‘ μ½κ΅
open_now(μ§κΈ μμ μ€) λ λ°μ΄ν° κ°±μ κ³Ό λ³κ°λ‘ λμ보λ λ λ μλ§λ€ μ€μκ° μ¬κ³μ°.
λ³Έ μ»΄ν¬λνΈλ μΌλΆ μλΉμ€μμ λΉκ³΅μ κ²½λ‘(μ€ν¬λνΒ·λͺ¨λ°μΌ μ± API)λ₯Ό μ¬μ©ν©λλ€. μΈλΆ μ¬μ΄νΈ λ³κ²½ μ μΌμμ μΌλ‘ κΉ¨μ§ μ μλ μ½μ μ λͺ¨λ 곡κ°ν©λλ€.
| μλΉμ€ | νκ³ |
|---|---|
| π¨ μμ μλ¦Ό / π’ μ¬λλ¬Έμ | safekorea.go.kr HTML μ€ν¬λν / safetydata.go.kr API. μ λΆ μ¬μ΄νΈ μ κ² μ μΌμ λ―Έμλ κ°λ₯. μ¬λλ¬Έμλ chrome 5μ’
impersonation rotation μ§μ, μμ μλ¦Όμ chrome120 λ¨μΌ |
| β‘ KEPCO | νμ νμ΄μ§λͺ
λ³κ²½ μ λ‘κ·ΈμΈ κ°μ§ μ€ν¨ κ°λ₯ (2FA λ―Έμ§μ). HA λ‘κ·Έ KEPCO login: unknown redirect λ‘ λλ²κΉ
|
| π§ μ리μ | μμΈμμ² νμ΄μ§(i121.seoul.go.kr) HTML ꡬ쑰 λ³κ²½ μ νμ± μ€ν¨ κ°λ₯. 9μ리 μμ©κ°λ²νΈ κ°μ |
| π κ°μ€μ± | λͺ¨λ°μΌ μ± λ΄λΆ API. ν¨ν· μΊ‘μ²(mitmproxy/Charles)λ‘ ν ν° μΆμΆ νμ β μΌλ° μ¬μ©μμκ² λΆλ΄ νΌ |
| π«οΈ μμ΄μ½λ¦¬μ μνμ§μ (UVΒ·λκΈ°μ 체) | μ½λλ V4 endpoint νΈμΆ, ν¬νΈμ V5λ‘ μ κ·Έλ μ΄λλ λ― β μ€μ λμ λ―Έκ²μ¦. λ―ΈμΈλ¨Όμ§(νμ 2건)λ μν₯ μμ |
| π« NEIS | λ°μ΄ν° μλ λ (λ°©νΒ·ν΄μΌ)μ INFO-200 μλ΅μ μλ¬λ‘ μ²λ¦¬ β μΌμ μλ¬ λ‘κ·Έ κ°λ₯ (μ€μ λμμλ μν₯ μ μ) |
β κ²μ¦ μλ£: μ½κ΅ (μν₯μ β μ€μ sensor state=20, 20κ° μ½κ΅ attribute μ μ). μμ μλ¦Ό (μν₯μ μνλ cascading λ±λ‘ μ±κ³΅). μ¬λλ¬Έμ (safetydata.go.kr ν€ λ°κΈ β entity μ μ λμ, 2026-05-14).
π μ¬μ΄νΈ λ³κ²½μΌλ‘ κΉ¨μ‘λ€λ©΄ GitHub Issuesμ μλ €μ£ΌμΈμ. λΉ λ₯΄κ² μμ PR μμ±ν©λλ€.
- μ μ² ν νμ±νκΉμ§ 1~2μκ° λκΈ° (νΉν μ΄μκΈ°κ΄ ν€)
data.go.krμμμλ λ°μ΄ν°μ λ³ νμ©μ μ² λ³λ β μ½κ΅ ν€λ‘ κΈ°μνΉλ³΄ νΈμΆνλ©΄ 403- μ¬λλ¬Έμλ
safetydata.go.krλ³λ ν¬νΈ βdata.go.krν€λ‘λ μ λ¨ 401= ν€ μμ²΄κ° μλͺ»,403= ν€λ λ§μ§λ§ ν΄λΉ λ°μ΄ν°μ νμ©μ μ² μ λ¨- μΌμΌ νΈλν½ νλ μ΄κ³Όλ λμΌ μ¦μ (λ§μ΄νμ΄μ§μμ νμΈ)
- μΉμ¬μ΄νΈμμ μ§μ λ‘κ·ΈμΈ κ°λ₯νμ§ νμΈ
- 2μ°¨ μΈμ¦(OTP) μ€μ λ κ³μ μ λ―Έμ§μ
- κ°μ€μ±μ ν ν°μ΄ μμ£Ό λ§λ£ β μ±μμ λ€μ λ°κΈ
- λ±λ‘ν μ§μμ μ΅κ·Ό λ©μμ§κ° μμΌλ©΄ sensor stateκ°
μμβ μ μ λμ - μ λΆ μ¬μ΄νΈ μ κ² μ€μ΄λ©΄ μ μ ν μλ 볡ꡬ
- λ‘κ·Έ νμΈ β μ€μ β μμ€ν
β λ‘κ·Έ μμ
kr_component_kitκ²μ - μ΄μ λ±λ‘ β GitHub Issues β λ€μ μ 보 ν¬ν¨:
- μ΄λ€ μλΉμ€ (μ: "μ½κ΅ β μμΈ κ°λ¨κ΅¬")
- HA λ²μ + λ³Έ μ»΄ν¬λνΈ λ²μ
- λ‘κ·Έ μλ¬ (κ°μΈμ 보·ν€λ κ°λ¦° ν)
- μλν λ¨κ³
π¬ νκ΅μ΄ κ·Έλλ‘ μμ±ν΄μ£Όμ λ λ©λλ€. λ΅λ³λ νκ΅μ΄λ‘.
- Home Assistant 2023.1.0 μ΄μ
- Python 3.11 μ΄μ (HA μ체 μꡬμ¬ν)
- μΈν°λ· μ°κ²° (κ° μλΉμ€ API μ κ·Ό)
- μλ μ€μΉ ν¨ν€μ§:
curl_cffi>=0.7.0,beautifulsoup4>=4.12.0(manifest.json μ μ)
- λ³Έ μ»΄ν¬λνΈλ μΌλΆ μλΉμ€μμ 곡μ APIκ° μλ μΈμ¦λ μΉ μ€ν¬λν / λͺ¨λ°μΌ μ± λ΄λΆ API λ₯Ό μ¬μ©ν©λλ€ (KEPCO, μ리μ, κ°μ€μ±, μμ μλ¦Ό)
- κ° μλΉμ€ μ 곡μ 체μ μ μ± λ³κ²½μ λ°λΌ λμνμ§ μμ μ μμ΅λλ€
- μ λΆ μ¬μ΄νΈ μΌλΆλ TLS κ²μ¦ μ°ν (
verify=False) β μ λΆ μ¬μ΄νΈμ TLS μ€μ νΈνμ± μ΄μ ννΌμ©. 보μμ λ―Όκ°νμλ©΄ μ½λλ₯Ό μ§μ νμΈν΄ μ£ΌμΈμ - κ°μΈμ 보(ID/λΉλ°λ²νΈ/ν ν°/API ν€)λ Home Assistant λ΄λΆ μ μ₯μμλ§ λ³΄κ΄λλ©° μΈλΆ μ μ‘ μμ
- λ³Έ νλ‘μ νΈλ μ λΆΒ·κ³΅κ³΅κΈ°κ΄κ³Ό 무κ΄ν λΉκ³΅μ μλνν° ν΅ν©. μ¬μ©μμ μ± μ νμ μ΄μ©ν΄ μ£ΌμΈμ.
λ³Έ ν΅ν©μ λ²μ€ λͺ¨λ λ κ°λ λ€μ μ€νμμ€ νλ‘μ νΈλ€μ μμ μ μ°Έκ³ /κ³μΉν΄ λ§λ€μ΄μ‘μ΅λλ€. κ° μμμλΆλ€κ» κΉμ΄ κ°μ¬λ립λλ€.
| λͺ¨λ | μμμ | μλ³Έ |
|---|---|---|
π νκ΅ λ²μ€ (korea_bus/) |
luiseok | https://github.com/luiseok/ha-korea-bus-arrival |
π μμΈλ²μ€ (seoul_bus/) μμ‘° |
miumida | https://github.com/miumida/seoul_bus |
π μμΈλ²μ€ (seoul_bus/) ν¨ν΄ |
Murianwind | https://github.com/Murianwind/seoul_bus |
κΈ°λ³Έ νλ¦μ μ μμλ€μμ κ°μ Έμκ³ , μ΄λ₯Ό kr_component_kit μ ν΅ν© ν¨ν΄μΌλ‘ ν‘μνλ©΄μ λ€μ λΆλΆμ λ³΄κ° / μΆκ°νμ΅λλ€:
- λ νλ¦ λ¨μΌ ν΅ν© β μΉ΄μΉ΄μ€λ§΅(νκ΅λ²μ€) + μμΈ κ³΅μ API(μμΈλ²μ€) λ₯Ό λ©λ΄ ν κ³³μμ
- λ§μ΄κ·Έλ μ΄μ
μμ λ§ β
kakao_busβkorea_busλλ©μΈ λ³κ²½, entity_id suffix μ μ μ μ¬μ©μ μλνκ° κΉ¨μ§μ§ μλλ‘async_migrate_entry - TIMESTAMP κΈ°λ° sensor β HA Weather μΉ΄λμ²λΌ "NλΆ ν" μλ νμ
- stale-data 보쑴 β μΌμμ API μ€λ₯ μ μ§μ κ° μ μ§
- νμ±ν μ€μμΉ (Murianwind ν¨ν΄ κ³μΉ) + μλ‘κ³ μΉ¨ λ²νΌ
- μ μλ²μ€ / λ§μ°¨ binary_sensor (μμΈ μ λ₯μμ 보쑰ν μλ΅μ
busType/isFullFlag/congestionνμ©) - λ€μ€ μ λ₯μ₯ / μ΅μ λ©λ΄ λ‘ μ λ₯μ₯ μΆκ°Β·μμ Β·λ Έμ νΈμ§ κ°λ₯
- 8κ° μλν λΈλ£¨νλ¦°νΈ (μΆλ° / νμ°¨ / λ§μ°¨ / λ§μ°¨ / μ λ₯μ₯ κ·Όμ² / μ§ λ λ λ / λͺ©μ μ§ λμ°© / μΆν΄κ·Ό μλ)
- i18n 4 lang (strings + en + ko + ja)
μμμ΄ μμλ€λ©΄ μ΄ ν΅ν©λ μμμ΅λλ€. π
- λΌμ΄μ μ€: MIT β μμ λ‘κ² μ¬μ©Β·μμ Β·μ¬λ°°ν¬ κ°λ₯
- μ΄μΒ·PR νμ: https://github.com/redchupa/kr_component_kit/issues
- μ νκ΅ μλΉμ€ μΆκ° μ μλ νμν©λλ€
μ€λ₯Έμͺ½ μλ¨ Star β ν λ²μ΄λ©΄ ν° λμμ΄ λ©λλ€. λ³μ΄ λͺ¨μ΄λ©΄ HACS Default Repository λ±λ‘ κ°λ₯μ±μ΄ μ¬λΌκ°κ³ , λ λ§μ νκ΅ μ¬μ©μκ° λ°κ²¬ν μ μμ΅λλ€.
μ΄ νλ‘μ νΈκ° λμμ΄ λμ ¨λ€λ©΄ μ»€νΌ ν μμΌλ‘ μμν΄ μ£ΌμΈμ π
ν μ€
|
PayPal
|
Made with β€οΈ for Korean Home Assistant Users

