An open API service indexing awesome lists of open source software.

https://github.com/redchupa/kr_component_kit

πŸ‡°πŸ‡· Home Assistant integration for Korea-only services: KEPCO, Arisu water, safety alerts, GasApp, Kakao Map, GoodsFlow, and more public services.
https://github.com/redchupa/kr_component_kit

custom-component custom-components hacs hacs-integration home-assistant home-automation homeassistant kepco korea korean smart-home

Last synced: 27 days ago
JSON representation

πŸ‡°πŸ‡· Home Assistant integration for Korea-only services: KEPCO, Arisu water, safety alerts, GasApp, Kakao Map, GoodsFlow, and more public services.

Awesome Lists containing this project

README

          

# πŸ‡°πŸ‡· KR Component Kit

> **A Home Assistant integration for Korean residents** β€” KEPCO electricity, Seoul water, city gas, KMA weather, government disaster alerts, pharmacy info, school meals, real-time public transit + dedicated Seoul Bus + nationwide bus, air quality, fuel prices, and earthquake warnings β€” 15 Korea-only public services bundled in one package.

πŸ‡°πŸ‡· [ν•œκ΅­μ–΄ README](README.md) Β· πŸ‡¬πŸ‡§ **English (this page)**

[![hacs][hacsbadge]][hacs]
[![GitHub Release][releases-shield]][releases]
[![GitHub Activity][commits-shield]][commits]
[![License][license-shield]](LICENSE)
[![Stargazers][stars-shield]][stars]

[![Open your Home Assistant instance and open a repository inside the HACS.](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?owner=redchupa&repository=kr_component_kit&category=integration)

---

## Why this exists

Korean public services don't have a standard OpenAPI surface like utilities elsewhere. Each agency runs its own portal (`data.go.kr`, `safetydata.go.kr`, `opinet.co.kr`, `open.neis.go.kr`, `data.seoul.go.kr`), with its own signup, its own dataset-by-dataset ν™œμš©μ‹ μ²­ (use application), and its own quirks.

This integration wraps the 15 most useful Korea-only services into one Home Assistant integration, with a unified config flow, native HA entities (sensors, weather, event, calendar, button), and an optional LLM tool surface for natural-Korean voice queries.

**Who this is for:**
- Korean residents (citizens, expats, or international residents) running Home Assistant
- Korean expats abroad monitoring family-home utilities or disaster alerts back home
- Anyone integrating Korean weather/air-quality data into a global HA setup

---

## πŸš€ 5-minute quickstart

### Step 1. Install (2 min)

Click the **`MY` HACS badge** at the top β€” your Home Assistant opens automatically, lands on the HACS download screen β†’ **DOWNLOAD** β†’ **restart Home Assistant**.

*No HACS yet? β†’ [HACS official setup guide](https://www.hacs.xyz/docs/setup/download/) first.*

### Step 2. Register your first service (1 min) β€” **no API key needed**

**Settings β†’ Devices & Services β†’ + Add Integration**
β†’ Search `ν•œκ΅­ μ»΄ν¬λ„ŒνŠΈ ν‚€νŠΈ` *(the Korean name; English domain `kr_component_kit` also works)*
β†’ Select **🚨 μ•ˆμ „μ•Œλ¦Ό (Safety Alert)** β†’ pick μ‹œλ„ (province) / μ‹œκ΅°κ΅¬ (city/district) / 읍면동 (town) β†’ Submit.

### Step 3. Verify (30 sec)

**Developer Tools β†’ States** β†’ search for the friendly name `μ΅œμ‹  μ•ˆμ „μ•Œλ¦Ό` ("Latest Safety Alert") β†’ state shows the most recent Korean government safety bulletin for your area.

### Step 4. Add more services

When ready, follow the [πŸ”‘ API Key Guide](#-api-key-guide) below to add the other 14 services one by one.

---

## πŸ“‹ The 15 services at a glance

| Service | Category | API key | Notes |
|---|---|---|---|
| πŸ’Š **Pharmacy** (μ•½κ΅­) | Living | βœ… data.go.kr | Pharmacies near you with "open now" flag |
| 🚨 **Safety Alert** (μ•ˆμ „μ•Œλ¦Ό) | Safety | ❌ none | Government safety alerts (scraping) |
| πŸ“’ **Disaster Alert** (μž¬λ‚œλ¬Έμž) | Safety | βœ… safetydata.go.kr | Emergency text broadcasts in real time |
| πŸŒͺ️ **Weather Warning** (κΈ°μƒνŠΉλ³΄) | Safety | βœ… data.go.kr | 12 advisory types (rain, wind, cold, heat…) |
| 🌍 **Earthquake** (μ§€μ§„) | Safety | βœ… data.go.kr | Radius + magnitude filters |
| β›… **KMA Forecast** (λ™λ„€μ˜ˆλ³΄) | Weather | βœ… data.go.kr | Native HA Weather card |
| 🌫️ **AirKorea** (에어코리아) | Weather | βœ… data.go.kr (Γ—2) | PM10/PM2.5 + KHAI air-quality index |
| ⚑ **KEPCO** (ν•œκ΅­μ „λ ₯) | Utility | ❌ (own login) | Electricity usage + bill |
| πŸ’§ **Arisu** (μ„œμšΈ μƒμˆ˜λ„) | Utility | ❌ (account number) | Seoul tap water only |
| 🏠 **GasApp** (κ°€μŠ€μ•±) | Utility | ❌ (mobile-app token) | Packet capture required (advanced) |
| β›½ **Fuel** (μœ κ°€) | Living | βœ… opinet.co.kr | Province-level avg / lowest-price stations |
| 🏫 **School** (학ꡐ) | Living | βœ… open.neis.go.kr | Lunch menu, schedule, calendar |
| 🚌 **Transit** (λŒ€μ€‘κ΅ν†΅) | Living | Partial | Subway (Seoul) + bus by KakaoMap stop-ID. Single integration entry for both |
| 🚌 **Seoul Bus** (μ„œμšΈλ²„μŠ€) | Living | βœ… data.go.kr | Official Seoul Bus API (ARS-ID). Per-route arrival sensors + **low-floor + full-bus binary_sensors** + per-stop refresh button + activation switch. Add/remove stops from options menu |
| 🚍 **Korea Bus** (ν•œκ΅­ λ²„μŠ€) | Living | ❌ none | KakaoMap nationwide, **search by stop name**, configurable poll interval |

> πŸ’‘ **All services are free.** Korean public APIs are gratis; this integration adds no payment of its own.

---

## πŸ”‘ API Key Guide

> ⚠️ **Three common pitfalls**
> - Disaster alerts use `safetydata.go.kr` (Safety Data Portal) β€” **a different site** from `data.go.kr` (Public Data Portal). Separate signup.
> - Even within `data.go.kr`, each dataset needs **its own ν™œμš©μ‹ μ²­ (use application)** β€” a key approved for pharmacies returns 403 when called against weather warnings.
> - After applying, expect **1–2 hours of activation lag** (especially agency-issued keys).

Each "πŸ‘‰ Direct search" link below lands on the portal's search-results page with the Korean keyword pre-filled.

### πŸ’Š Pharmacy (μ „κ΅­ μ•½κ΅­ 정보)

| Field | Value |
|---|---|
| 🌐 Portal | [Public Data Portal (data.go.kr)](https://www.data.go.kr) |
| πŸ”Ž Direct search | [πŸ‘‰ Open pharmacy search](https://www.data.go.kr/tcs/dss/selectDataSetList.do?searchKeyword=μ „κ΅­%20μ•½κ΅­) |
| Search keyword | `μ „κ΅­ μ•½κ΅­` or `μ•½κ΅­ 정보` |
| Operating agency | National Medical Center (NMC) β€” code `B552657` |
| Exact dataset name | **κ΅­λ¦½μ€‘μ•™μ˜λ£Œμ›_μ „κ΅­ μ•½κ΅­ 정보 쑰회 μ„œλΉ„μŠ€** |
| Endpoint called by code | `apis.data.go.kr/B552657/ErmctInsttInfoInqireService/getParmacyListInfoInqire` |

**Steps:** Sign up at the portal (Korean OAuth via Naver/Kakao works) β†’ click the direct-search link β†’ pick the dataset β†’ **ν™œμš©μ‹ μ²­** (Use Application) β†’ My Page β†’ Open API β†’ Auth Key list β†’ copy the **Decoding** form β†’ paste into HA pharmacy field.

---

### πŸ“’ Disaster Alert (μž¬λ‚œλ¬Έμž) *(βœ… Verified working β€” 2026-05-14)*

| Field | Value |
|---|---|
| 🌐 Portal | [Safety Data Sharing Platform (safetydata.go.kr)](https://www.safetydata.go.kr) |
| Operating agency | Ministry of the Interior and Safety |
| Exact dataset name | **ν–‰μ •μ•ˆμ „λΆ€_κΈ΄κΈ‰μž¬λ‚œλ¬Έμž** (MOIS Emergency Disaster Alerts) |
| Endpoint | `/V2/api/DSSP-IF-00247` |
| Provisioning | **Manual operator review** β€” not auto-issued (1–3 business days) |
| Daily call quota | Default 1,000/day. Integration polls every 5 min β†’ 288 calls/day. Plenty of headroom. |
| Key validity | **1 year** *(renew on My Page before expiration β€” check the 만료일자 field on the key screen)* |
| Key form | **Single form only** *(unlike data.go.kr, there is no Decoding/Encoding split)* |
| IP required | ⚠️ **Application form requires registering the calling IP** (see Step 3) |

> ⚠️ Safety Data Sharing Platform and Public Data Portal are **separate sites** even though both are government-run. Sign up separately even if you already have a `data.go.kr` account.

#### 1️⃣ Sign up
Register at [safetydata.go.kr](https://www.safetydata.go.kr). Your `data.go.kr` credentials do **not** work here.

#### 2️⃣ Pick the correct dataset *(⚠️ two cards look similar)*
Top search box β†’ type `μž¬λ‚œλ¬Έμž` β†’ you'll see **two** result cards:

| Card | Use? |
|---|---|
| **ν–‰μ •μ•ˆμ „λΆ€_κΈ΄κΈ‰μž¬λ‚œλ¬Έμž** *(50k+ views / 28M downloads / `#μž¬λ‚œλ¬Έμž` tag)* | βœ… **This one** |
| μž¬λ‚œλ¬Έμž(속보) *(~900 views / tag `#-1`)* | ❌ Different endpoint code, incompatible with this integration |

Click the correct card β†’ confirm the endpoint code on the detail page is `DSSP-IF-00247`.

#### 3️⃣ Fill out the application form

On the detail page β†’ **μ˜€ν”ˆAPI ν™œμš©μ‹ μ²­** (Open API Use Application) button β†’ form fields:

**β‘  ν™œμš©λͺ©μ  (Purpose)** *(required)*
- Category: **`μ•±κ°œλ°œ (λͺ¨λ°”일, μ†”λ£¨μ…˜ λ“±)`** (App development) recommended
- Description example: *"Use in a Home Assistant integration to deliver real-time emergency disaster alerts to family members."*

**β‘‘ ν•˜λ£¨ μ΅œλŒ€ 호좜 횟수 (Daily call quota)** *(required)*
- Enter **`1000`**. Integration uses 288/day at the default 5-minute polling β€” well under the limit.

**β‘’ 아이피 (IP address)** *(required)* β€” most important field
You must register the **public outbound IP** of the machine running Home Assistant. If the registered IP doesn't match the actual request IP, the API returns **403 Forbidden** even with a valid key.

| Option | Example | Recommendation |
|---|---|---|
| Single IP | `121.123.45.67` | Strictest. But **Korean residential ISPs use dynamic IPs** β€” it'll change within days/months, requiring re-application |
| CIDR-like wildcard | `121.123.*.*` | Safer if your ISP rotates within the same range |
| Allow all | `*.*.*.*` | ⭐ **Recommended for personal use** β€” no need to track IP changes. The key itself is the secret; broad IP scope is fine for low-risk personal use |

πŸ”Ž **How to find your HA server's public IP:**
HA add-on β†’ **Terminal & SSH** (or SSH in) β†’ run:
```bash
curl -s https://api.ipify.org
```
Use whatever IP this prints in the application form.

**β‘£ License agreement checkbox** β†’ click **μ΄μš©μ‹ μ²­** (Submit).

#### 4️⃣ Wait for approval
My Page β†’ "데이터 ν™œμš©μ‹ μ²­ λ‚΄μ—­" (Application history) β€” check status:
- *"승인 λŒ€κΈ° μ€‘μž…λ‹ˆλ‹€"* (Pending review) β†’ an operator must approve it. **Not auto-issued β€” expect 1–3 business days.**
- *"λ°œκΈ‰λ¨"* (Issued) β†’ service key value becomes visible.

#### 5️⃣ Copy the key β†’ enter into HA
My Page β†’ click the **κ°’ λ³΅μ‚¬ν•˜κΈ° (Copy value)** button next to the issued key β†’ in HA, add integration β†’ pick **μž¬λ‚œλ¬Έμž** β†’ paste into the auth-key field as-is.

> πŸ’‘ safetydata.go.kr provides the key in **a single form** (no Decoding/Encoding split like data.go.kr). Whatever the **κ°’ λ³΅μ‚¬ν•˜κΈ°** button copies, paste it as-is. The integration handles URL encoding internally.

#### πŸ” After issuance

- **Quota monitoring**: My Page shows `μΌμΌν˜ΈμΆœλŸ‰ / ν˜ΈμΆœλŸ‰` β€” the first number is the limit (1000), the second is **cumulative usage today** (`0` means "not used yet today", not "max"). Resets at midnight KST.
- **Updating the registered IP**: If your dynamic IP changes, go to My Page β†’ key β†’ **λͺ©λ‘ λ³€κ²½μ‹ μ²­** (Edit application) β†’ update the IP field. ⚠️ Edits also go through operator review. If your IP rotates often, save yourself the loop and switch to `*.*.*.*` from the start.
- **Key expiration (1 year)**: Renew via λ³€κ²½μ‹ μ²­ before the 만료일자 date. Expired keys return 401.

#### πŸ†˜ Troubleshooting

| Symptom | Likely cause | Fix |
|---|---|---|
| `401 / SERVICE KEY ERROR` | Key not yet activated / expired / whitespace in pasted value | Wait 30–60 min after issuance. Check the 만료일자 (expiration date). Trim any leading/trailing whitespace and re-paste |
| `403 / ACCESS_DENIED` | **IP mismatch (most common cause)** | Compare `curl -s https://api.ipify.org` output against the IP registered in My Page. If they differ, update the registered IP via **λͺ©λ‘ λ³€κ²½μ‹ μ²­**. If it changes often, re-register with `*.*.*.*` |
| Empty response / `body []` | Normal β€” no recent disaster alerts in that time window | Quiet hours legitimately return empty. The feed fills up during major incidents or severe weather |

---

### πŸŒͺ️ Weather Warning + 🌍 Earthquake + β›… Short-term Forecast (3 KMA datasets, same key)

All three live under `data.go.kr`, operating agency **Korea Meteorological Administration (KMA)**, agency code `1360000`. **One auth key per account** β€” but each dataset still needs its own ν™œμš©μ‹ μ²­.

| Service | Direct search | Keyword | Endpoint |
|---|---|---|---|
| πŸŒͺ️ Weather warning | [πŸ‘‰ Search](https://www.data.go.kr/tcs/dss/selectDataSetList.do?searchKeyword=κΈ°μƒνŠΉλ³΄) | `κΈ°μƒνŠΉλ³΄` | `1360000/WthrWrnInfoService` |
| 🌍 Earthquake | [πŸ‘‰ Search](https://www.data.go.kr/tcs/dss/selectDataSetList.do?searchKeyword=지진정보) | `지진정보` | `1360000/EqkInfoService` |
| β›… Short-term forecast | [πŸ‘‰ Search](https://www.data.go.kr/tcs/dss/selectDataSetList.do?searchKeyword=λ‹¨κΈ°μ˜ˆλ³΄) | `λ‹¨κΈ°μ˜ˆλ³΄` | `1360000/VilageFcstInfoService_2.0` |

---

### 🌫️ AirKorea (Air Quality) β€” **two datasets required**

`data.go.kr`, operating agency **Korea Environment Corporation**, agency code `B552584`. Both datasets must be applied for separately.

| Dataset | Direct search | Keyword | Endpoint |
|---|---|---|---|
| Station info | [πŸ‘‰ Search](https://www.data.go.kr/tcs/dss/selectDataSetList.do?searchKeyword=에어코리아%20μΈ‘μ •μ†Œ) | `에어코리아 μΈ‘μ •μ†Œ` | `B552584/MsrstnInfoInqireSvc` |
| Pollution data | [πŸ‘‰ Search](https://www.data.go.kr/tcs/dss/selectDataSetList.do?searchKeyword=에어코리아%20λŒ€κΈ°μ˜€μ—Ό) | `에어코리아 λŒ€κΈ°μ˜€μ—Ό` | `B552584/ArpltnInforInqireSvc` |

> πŸ’‘ If station-info is missing, the station dropdown in HA setup will be empty.

> ⚠️ **Optional β€” Living Weather Index (UV / air stagnation)**: code calls the `V4` endpoint, but the portal seems to have moved to `V5`. Live operation unverified. If you want these sensors, search `μƒν™œκΈ°μƒμ§€μˆ˜` and apply; check HA logs (`Settings β†’ System β†’ Logs`, search `LivingWthrIdx`) for actual behavior. PM10/PM2.5 (the required two) are unaffected.

---

### β›½ Fuel (Opinet)

| Field | Value |
|---|---|
| 🌐 Portal | [πŸ‘‰ Opinet API signup page](https://www.opinet.co.kr/user/api/empApiInfo.do) |
| Process | Free signup β†’ API application β†’ immediate issuance |
| Endpoint | `opinet.co.kr/api/avgAllPrice.do`, `lowTop10.do` |

> πŸ’‘ Opinet is a **separate portal** from the Public Data Portal.

---

### 🏫 School (NEIS)

| Field | Value |
|---|---|
| 🌐 Portal | [πŸ‘‰ NEIS Education Open Portal](https://open.neis.go.kr) |
| Process | Sign up β†’ request auth key β†’ check My Page "Application Status" |
| Endpoint | `open.neis.go.kr/hub/...` |

> πŸ’‘ NEIS is also a **separate portal**. The HA config flow auto-searches schools by name β€” just type your school's Korean name into the dropdown.

---

### 🚌 Transit β€” keys depend on scenario

> βœ… **Live-verified** (2026-05-18): Korea Bus tested end-to-end on a real HA instance with two stops registered simultaneously β€” Seoul Sindorim.Guro Station (ARS 17003) and Gyeonggi Siheung Eungye-Umirin (ARS 25842). Per-route arrival sensors + refresh button + activation switch all working; every documented attribute (vehicle_number, current_stop, message, direction, bus_type, first_time / last_time / intervals, next_stop, status) confirmed against live KakaoMap responses.

| Use case | Key needed | Where |
|---|---|---|
| Subway arrivals | Seoul Open Data Plaza key | [πŸ‘‰ data.seoul.go.kr](https://data.seoul.go.kr) β†’ apply for `μ§€ν•˜μ²  μ‹€μ‹œκ°„ 도착정보` |
| Bus arrivals | **None needed** | KakaoMap's unofficial endpoint; just enter the stop ID |
| Transfer path search (optional) | Seoul transfer-route API key | [πŸ‘‰ data.go.kr](https://www.data.go.kr/tcs/dss/selectDataSetList.do?searchKeyword=λŒ€μ€‘κ΅ν†΅ν™˜μŠΉκ²½λ‘œ) β†’ `λŒ€μ€‘κ΅ν†΅ν™˜μŠΉκ²½λ‘œ` |

**Finding a KakaoMap bus stop ID** *(for bus registration)*:
[KakaoMap](https://map.kakao.com) β†’ search for the stop β†’ click it β†’ URL becomes `?busstopid=03171&...` β†’ **copy the value after `busstopid=`** (e.g., `03171`, `BS09013700`).

**Finding a Seoul Bus ARS-ID** *("Seoul Bus" menu)*:
[bus.go.kr](https://bus.go.kr) or the 5-digit number printed on the bus-stop sign itself (e.g., `23288` for 사당역).

---

### 🚌 Seoul Bus β€” API key guide (5 min)

| Field | Value |
|---|---|
| 🌐 Portal | [Public Data Portal (data.go.kr)](https://www.data.go.kr) |
| πŸ”Ž Direct link | [πŸ‘‰ μ„œμšΈνŠΉλ³„μ‹œ_μ •λ₯˜μ†Œμ •λ³΄μ‘°νšŒ μ„œλΉ„μŠ€](https://www.data.go.kr/data/15000303/openapi.do) |
| Provider | Seoul Metropolitan Government |
| Exact dataset name | **μ„œμšΈνŠΉλ³„μ‹œ_μ •λ₯˜μ†Œμ •λ³΄μ‘°νšŒ μ„œλΉ„μŠ€** |
| Endpoint called by code | `ws.bus.go.kr/api/rest/stationinfo/getStationByUid` |
| Daily call limit | 1,000 (plenty β€” activation switch keeps polling targeted) |

**Steps**:
1. Sign up at data.go.kr, click the link above
2. On the dataset page β†’ **ν™œμš©μ‹ μ²­** (Use Application) β†’ fill the form (auto-approved dataset; no IP registration needed)
3. My Page β†’ Open API β†’ Auth keys β†’ copy the **일반 인증킀** (regular auth key) value

> ⚠️ **Important β€” keys take ~24 hours to activate.**
>
> Even after the portal shows "μ²˜λ¦¬μƒνƒœ: 승인" (status: approved) and "ν™œμš©κΈ°κ°„: μ˜€λŠ˜λΆ€ν„°" (effective today), the actual API gateway's auth module needs **~24 more hours** to register the key. If you see "API key is not valid" right after applying, that's expected β€” **come back the next day and retry**.
>
> If still failing after 24 h:
> - Verify the dataset name is exactly **μ„œμšΈνŠΉλ³„μ‹œ_μ •λ₯˜μ†Œμ •λ³΄μ‘°νšŒ μ„œλΉ„μŠ€** (similarly-named datasets exist)
> - Call data.go.kr support at **1566-0025**
> - Or unregister + re-apply on My Page (gets a fresh key)

---

### πŸ”Œ Activation switch β€” shared between Seoul Bus / Korea Bus

Both flows create a `switch.__update_active` entity per stop. The coordinator only polls the API **while this switch is ON**. When OFF it keeps the last fetched data on the entities and skips the API call entirely.

**Why useful**:
- Saves daily-quota calls (especially Seoul Bus 1,000/day limit)
- No reason to poll at 4 AM or while you're away
- HA automations can flip it on/off precisely when needed

**Defaults**:
- Fresh install β†’ **starts ON** (data shows up immediately)
- After restart β†’ RestoreEntity restores the user's last ON/OFF choice

**Automation example β€” poll only during commute windows + proximity**:

```yaml
alias: Toggle bus polling by time + distance
mode: restart
triggers:
- at: "06:30:00" # morning commute window opens
id: morning_on_time
trigger: time
- entity_id: sensor.
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:
- conditions: # morning + workday + near home
- 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
- conditions: # moved away from stop β†’ OFF
- condition: trigger
id: morning_off_dist
sequence:
- service: switch.turn_off
target:
entity_id: switch.seoul_bus_*****_update_active
- conditions: # evening commute opens
- condition: trigger
id: evening_on_time
sequence:
- service: switch.turn_on
target:
entity_id: switch.seoul_bus_*****_update_active
- conditions: # arrived home β†’ OFF
- condition: trigger
id: evening_off_dist
sequence:
- service: switch.turn_off
target:
entity_id: switch.seoul_bus_*****_update_active
```

β†’ Zero API calls outside commute windows.

**Conditional dashboard card** (with HACS `state-switch`):
```yaml
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 # card disappears when switch is OFF
```

---

### βš™οΈ Stop management (Seoul Bus / Korea Bus)

You don't need to delete-and-re-register to add stops or change routes:

**Settings β†’ Devices & Services β†’ "ν•œκ΅­ μ»΄ν¬λ„ŒνŠΈ ν‚€νŠΈ" card β†’ "Configure"** β†’ menu:

| Menu item | Action |
|---|---|
| 🚏 Add stop | New stop (Seoul: enter ARS-ID / Korea Bus: search by name) |
| πŸ—‘ Remove stop(s) | Multi-select |
| 🚌 Edit routes for a stop | Change which routes get tracked for an existing stop |
| πŸ”‘ Change API key (Seoul only) | Live-validates the new key before saving |
| ⏱ Change poll interval (Korea Bus only) | 30 s ~ 1 h |
| βœ… Save & Finish | Commit all changes + auto-reload |

Closing with the X discards pending edits (transactional pattern).

---

### 🎁 8 ready-made automation blueprints

#### Seoul Bus ↔ Korea Bus compatibility

| Blueprint | 🚌 Seoul Bus | 🚍 Korea Bus |
|---|:---:|:---:|
| Departure alert | βœ… | βœ… |
| Get-off alert | βœ… | βœ… |
| Last-bus alert | βœ… | βœ… |
| Full / crowded alert | βœ… | ❌ (KakaoMap response lacks full-bus field) |
| Proximity polling toggle (location-aware) | βœ… | βœ… |
| Leaving-home alert (location-aware) | βœ… | βœ… |
| Destination-arrival get-off alert (location-aware) | βœ… | βœ… |
| Commute auto mode (location-aware) | βœ… | βœ… |

β†’ **7 of 8 work on either flow**. Korea Bus users get the full automation toolbox bar one Seoul-only feature.

#### Notify input β€” action selector

Every blueprint's notify input is an **HA action selector**. On import:
- pick your notify service (e.g. `notify.mobile_app_my_phone`) from the UI dropdown
- the default `title` / `message` use `{{ alert_title }}` / `{{ alert_message }}` β€” internal variables fill these for you
- feel free to swap in `notify.telegram`, `media_player.tts.google_say`, or any other action you prefer

Patterns from Korea's public-data bus-app catalog, shipped as HA blueprints.

| Blueprint | Trigger | Use case |
|---|---|---|
| 🚌 **Departure alert** | `native_value (TIMESTAMP)` enters N-minute window | "Bus arrives in N min. Leave home now." push |
| πŸ”” **Get-off alert** | `current_stop` attribute changes | While on the bus, alert N stops before destination |
| πŸŒ™ **Last-bus alert** | `last_vehicle` / `is_last` attribute flips | "This is the last bus tonight" push |
| 🚨 **Full / crowded alert** | full binary_sensor goes ON + `congestion` changes | Seoul Bus only β€” pings the next-bus ETA |

**Import** (one-click via UI):

1. HA β†’ Settings β†’ Automations β†’ Blueprints β†’ **Import Blueprint**
2. Paste one of these URLs β†’ **Preview** β†’ **Import**

```
Departure: https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/bus_departure_alert.yaml
Get-off: https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/bus_alight_alert.yaml
Last bus: https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/bus_lastride_alert.yaml
Full/crowd: https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/bus_crowded_alert.yaml
```

3. **Create Automation** β†’ pick the blueprint β†’ fill in sensor + notify target + minutes β†’ Save

> πŸ’‘ Push notifications use **HA Companion App** (iOS / Android) β€” the service name is `notify.mobile_app_` where `` is whatever you set during Companion App registration.

---

### πŸ“± 4 location-aware blueprints β€” leverages HA Companion App device tracking

Use the **device_tracker** from your phone (auto-tracked by Companion App) to build automations a regular bus app can't.

| Blueprint | What it does |
|---|---|
| 🚏 **Proximity-based polling toggle** | Phone enters bus-stop zone β†’ activation switch ON; leaves β†’ OFF after N min |
| 🏠 **Leaving-home alert** | Phone leaves `zone.home` β†’ push the next bus ETA |
| πŸ“ **Destination-arrival get-off alert** | Phone enters destination zone β†’ push ("get ready to get off") β€” **catches you even if you fell asleep on the bus** |
| 🌍 **Auto commute mode** | Time + location β†’ switch auto ON/OFF (mirrors the upstream Murianwind/seoul_bus automation pattern) |

**Prerequisite β€” make the zones**:
1. HA β†’ Settings β†’ **Areas & Zones** β†’ Add Zone
2. Enter the lat/lon of the bus stop (or office/school) β€” find on [KakaoMap](https://map.kakao.com)
3. Radius: 100–200 m for stops, 200–300 m for workplaces

**Import URLs**:
```
Proximity toggle: https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/stop_proximity_toggle.yaml
Leaving-home alert: https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/leaving_home_alert.yaml
Arrival alight alert:https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/arrival_alight_alert.yaml
Commute auto mode: https://github.com/redchupa/kr_component_kit/blob/main/blueprints/automation/kr_component_kit/commute_auto_mode.yaml
```

Compose them:
- Proximity toggle + leaving-home alert β†’ polling starts automatically when you head out, plus the next bus ETA push
- Arrival alight alert β†’ no more missed stops if you doze off on the bus
- Commute auto mode β†’ polls only when you're realistically using the bus (saves daily-quota calls)

---

## βš™οΈ Registration & reconfiguration

### Adding a new entry
Settings β†’ Devices & Services β†’ **+ Add Integration** β†’ `ν•œκ΅­ μ»΄ν¬λ„ŒνŠΈ ν‚€νŠΈ` β†’ pick service.

> One integration menus 13 services β€” add them one at a time. **Same service can be registered multiple times for different regions** (e.g., pharmacy for your district + your in-laws' district = 3 separate entries).

### Changing API keys / regions after setup
The relevant entry's **"Configure"** button β†’ edit. *(No need to delete-and-reregister; entities and automations preserved.)*

### Where to get each non-API-key input

| Service | Where |
|---|---|
| ⚑ **KEPCO** | Your KEPCO website ID / password (2FA not supported) |
| πŸ’§ **Arisu** | Paper bill or [Arisu Cyber Customer Center](https://i-arisu.seoul.go.kr) β†’ μš”κΈˆμ‘°νšŒ (Bill Inquiry) β†’ left sidebar shows μˆ˜μš©κ°€λ²ˆν˜Έ (customer number) + 고객λͺ… (customer name) |
| 🏠 **GasApp** | Contract number from the GasApp mobile app β†’ My Info. Token + member ID via packet capture (mitmproxy / Charles) of the mobile-app HTTPS request headers `X-Token` / `X-Member` (⚠️ advanced) |
| 🌍 **Earthquake coordinates** | Defaults to Seoul City Hall (`37.5665, 126.978`). **Set your home coordinates.** Default radius 200 km / minimum magnitude 3.0 |

---

## 🎁 Entities you'll get

> Entity IDs are auto-romanized from Korean (e.g., device `μ•½κ΅­ - μ‹œν₯μ‹œ` + entity `운영 μ•½κ΅­ 수` β†’ `sensor.yaggug_siheungsi_unyeong_yaggug_su`). To find the exact ID, search by **friendly name** in Developer Tools β†’ States.

| Service | Friendly names | Key attributes |
|---|---|---|
| πŸ’Š Pharmacy | `운영 μ•½κ΅­ 수` ("Operating Pharmacy Count") | `pharmacies[]` (up to 50: name/address/phone/lat/lon/today_hours/`open_now`/duty_time), `total`, `shown`, `open_now_count` |
| 🚨 Safety Alert | `μ΅œμ‹  μ•ˆμ „μ•Œλ¦Ό`, `μ•ˆμ „μ•Œλ¦Ό 수`, `였늘 μ•ˆμ „μ•Œλ¦Ό μ—¬λΆ€` (binary), `μ•ˆμ „μ•Œλ¦Ό 이벀트` (event) | `latest`, `alerts[]`, `count` |
| πŸ“’ Disaster Alert | `μ΅œμ‹  μž¬λ‚œλ¬Έμž`, `μž¬λ‚œλ¬Έμž 수`, `μž¬λ‚œλ¬Έμž 이벀트` (event) | `level`, `area`, `disaster_type` |
| πŸŒͺ️ Weather Warning | `호우 특보`/`강풍 특보`/`ν•œνŒŒ 특보`/... (12 event entities) | state: `advisory`/`warning`/`pre_*`/`cancelled`/`none`, `start_time`, `end_time` |
| 🌍 Earthquake | `μ§€μ§„ 경보` (event) | `magnitude`, `location`, `distance_km`, `datetime` |
| β›… Forecast | Single weather entity β€” compatible with HA's standard Weather card | hourly/daily forecast service |
| 🌫️ AirKorea | `PM10 λ―Έμ„Έλ¨Όμ§€`, `PM2.5 μ΄ˆλ―Έμ„Έλ¨Όμ§€`, `O₃ 였쑴`, `NOβ‚‚`, `SOβ‚‚`, `CO`, `ν†΅ν•©λŒ€κΈ°μ§ˆμ§€μˆ˜` + binary `λŒ€κΈ°μ§ˆ 경보` + event + calendar `λŒ€κΈ°μ§ˆ 예보` | Grade attribute attached |
| ⚑ KEPCO | `ν˜„μž¬ μ‚¬μš©λŸ‰` (kWh), `μ§€λ‚œλ‹¬ μš”κΈˆ` (KRW), `μ˜ˆμƒ μš”κΈˆ`, `고객번호`, `μ „λ ₯ꡬ뢄` | β€” |
| πŸ’§ Arisu | `μˆ˜λ„ μš”κΈˆ` (KRW), `μ‚¬μš©λŸ‰` (γŽ₯), `청ꡬ월` | `billing_month`, `customer_info`, `arrears_info` |
| 🏠 GasApp | `청ꡬ 제λͺ©`, `총 μš”κΈˆ` (KRW) | β€” |
| β›½ Fuel | `μ „κ΅­ 평균가`, `μ΅œμ €κ°€` (per sido Γ— fuel-type combo) | `ranking[]` (top 5 stations) |
| 🏫 School | `급식` ("Lunch"), `학ꡐ 정보` + calendar entities for academic schedule and timetable | Lunch: `menu`, `calorie`, `allergy_codes` |
| 🚌 Transit | ` ... 도착` (TIMESTAMP β€” HA auto-shows "N min later") | β€” |

---

## πŸ€– Natural-language queries (LLM, optional)

If you expose this integration to HA's **Assist + LLM** (OpenAI / Google / Ollama / etc.), you can ask in natural Korean:

| Query | Service |
|---|---|
| "μ§€κΈˆ μ˜μ—…μ€‘μΈ κ°€κΉŒμš΄ μ•½κ΅­ μ•Œλ €μ€˜" ("Find nearby pharmacies open now") | πŸ’Š Pharmacy |
| "였늘 λ―Έμ„Έλ¨Όμ§€ μ–΄λ•Œ?" ("How's the air quality today?") | 🌫️ AirKorea |
| "내일 λΉ„ 와?" ("Will it rain tomorrow?") | β›… KMA |
| "였늘 급식 뭐야?" ("What's for school lunch today?") | 🏫 School |
| "λ‹€μŒ λ²„μŠ€ μ–Έμ œ 와?" ("When's the next bus?") | 🚌 Transit |

Without LLM exposure, regular sensor/event/weather entities work as normal β€” no extra setup required.

---

## ❓ FAQ

Do I have to register all 13 services?

No. Register only what you want. Services you don't register create zero entities and consume no resources.

Are any of these paid?

**All free.** Korean government / public-corporation OpenAPIs; this integration adds no cost of its own. Each API has daily call quotas (typically 10,000 – 1,000,000/day) β€” never an issue for single-household use.

I'm intimidated by API key signups. What can I try first?

**Four services work without any API key**:
- 🚨 **Safety Alert** β€” pick a region (scraping-based)
- ⚑ **KEPCO / πŸ’§ Arisu / 🏠 GasApp** β€” your own account (not an API key)

I live outside Seoul. Does this work?

Most services work nationwide. **Seoul-only**: Arisu (water), Seoul subway real-time arrivals. Everything else is countrywide.

How do I change my API key or region after setup?

Settings β†’ Devices & Services β†’ **ν•œκ΅­ μ»΄ν¬λ„ŒνŠΈ ν‚€νŠΈ** card β†’ that entry's **Configure** button β†’ edit. No delete-and-reregister needed; entities + automations preserved.

Can I register the same service multiple times for different regions?

Yes. Register the pharmacy service for your district + your in-laws' district + your parents' district β€” three independent device/entity sets.

How do I send phone notifications when an alert comes in?

Combine HA Automation with the Companion app's `notify.mobile_app_*` service. Minimal example:

```yaml
automation:
- alias: "Disaster alert β†’ phone push"
trigger:
- platform: state
entity_id: sensor.
condition:
- condition: template
value_template: "{{ trigger.to_state.state not in ['μ—†μŒ', 'unknown', 'unavailable'] }}"
action:
- service: notify.mobile_app_
data:
title: "🚨 Disaster Alert"
message: "{{ trigger.to_state.state }}"
```

Look up entity IDs by friendly name in Developer Tools β†’ States.

Where are my credentials stored?

In Home Assistant's internal storage (`.storage/`) only. Passwords are sent only to the respective service's official login page (e.g., KEPCO / Arisu). See [Disclaimer](#️-disclaimer).

How do I update?

HACS shows a red dot on **HACS β†’ Integrations β†’ KR Component Kit** when a new release is available. Click β†’ UPDATE β†’ restart HA. Existing config + entities preserved.

My new-build apartment isn't in the district dropdown.

Government administrative codes occasionally lag for newly-built areas. Pick the nearest adjacent district. KMA forecasts are 5 km Γ— 5 km grids anyway, so the actual weather data is nearly identical.

---

## πŸ”„ Update intervals

| Category | Service | Interval |
|---|---|---|
| Real-time | Bus / Subway | 1–2 min |
| Safety | Disaster, Safety Alert, KEPCO | 5 min |
| Safety | Earthquake, Weather Warning | 10–15 min |
| Environment/Utility | GasApp, KMA Forecast, AirKorea | 20–30 min |
| Living | Arisu, Pharmacy, Fuel | 1 hour |
| Living | School (meals/timetable) | 6 hours |

> πŸ’‘ Pharmacy `open_now` (currently open) is **recomputed live each dashboard render** independently of data refresh.

---

## ⚠️ Known limitations (honest disclosure)

Some services use non-official paths (HTML scraping, mobile-app APIs). External-site changes can temporarily break them. All known weak spots:

| Service | Limit |
|---|---|
| 🚨 **Safety Alert / πŸ“’ Disaster Alert** | `safekorea.go.kr` HTML scraping / `safetydata.go.kr` API. May break during government-site maintenance. Disaster Alert uses 5-profile Chrome impersonation rotation; Safety Alert uses single `chrome120` profile |
| ⚑ **KEPCO** | Login-success URL markers are hardcoded β€” if KEPCO renames its post-login page, detection fails. 2FA not supported. Look for `KEPCO login: unknown redirect` in HA logs to debug |
| πŸ’§ **Arisu** | HTML scraping of `i121.seoul.go.kr` β€” Seoul city website structure changes can break parsing. Assumes 9-digit customer number |
| 🏠 **GasApp** | Uses the mobile-app internal API. Token extraction requires packet-capture tooling (mitmproxy / Charles) β€” high barrier for non-technical users |
| 🌫️ **AirKorea Living Index (UV / air stagnation)** | Code calls `V4` endpoint, but the portal seems upgraded to `V5` β€” live operation unverified. Required pollution datasets are unaffected |
| 🏫 **NEIS** | `INFO-200` (no-data, normal) is currently treated as an error β€” log noise possible on school holidays / vacation periods (no functional impact) |

> βœ… **Verified working** as of release `v4.2.18`: Pharmacy (live HA query showed sensor state=20 with full attribute payload). Safety Alert (cascading district registration successful). Disaster Alert (safetydata.go.kr key issued β†’ entities live, 2026-05-14).

> πŸ› **Something broke after a site change?** Open a [GitHub issue](https://github.com/redchupa/kr_component_kit/issues) and a fix PR is usually quick.

---

## πŸ› Troubleshooting

### API key auth failures
- After applying, expect **1–2 hours** of activation lag (especially agency-issued keys)
- Within `data.go.kr`, **each dataset needs its own ν™œμš©μ‹ μ²­** β€” a pharmacy-approved key returns 403 against weather warnings
- Disaster Alert needs `safetydata.go.kr` specifically β€” `data.go.kr` keys do not work
- `401` = wrong key, `403` = right key but no application approval for that dataset
- Hit daily quota? Check My Page traffic stats

### Login failures (KEPCO / Arisu / GasApp)
- Confirm the website itself lets you log in normally
- Accounts with 2FA enabled are not supported
- GasApp tokens expire frequently β€” re-extract from the app

### Empty data (Safety Alert / Disaster Alert)
- If no recent messages in your area, state shows `μ—†μŒ` ("none") β€” normal
- Government site maintenance? Wait and it auto-recovers

### Still stuck

1. **Check logs** β€” Settings β†’ System β†’ Logs β†’ search `kr_component_kit`
2. **Open an issue** β€” [GitHub Issues](https://github.com/redchupa/kr_component_kit/issues) β€” include:
- Which service (e.g., "Pharmacy β€” Seoul Gangnam-gu")
- HA version + this integration version
- Error log (mask any personal info / keys)
- Steps you've tried

> πŸ’¬ Both English and Korean issues welcome β€” responses in your language.

---

## πŸ“‹ Requirements

- **Home Assistant** 2023.1.0 or later
- **Python** 3.11+ (HA's own requirement)
- Internet connection (each service hits its respective API)
- Auto-installed Python packages: `curl_cffi>=0.7.0`, `beautifulsoup4>=4.12.0` (declared in manifest.json)

---

## ⚠️ Disclaimer

- This integration uses **authenticated web scraping or mobile-app internal APIs** rather than official OpenAPIs for KEPCO, Arisu, GasApp, and Safety Alert
- Provider policy changes may break these services without warning
- A few government-site clients use `verify=False` (TLS-verification bypass) to work around the sites' TLS configuration quirks β€” review the source if this concerns you
- All credentials (IDs, passwords, tokens, API keys) are stored only in Home Assistant's local storage. Nothing is sent externally
- This is an **unofficial third-party integration** β€” not affiliated with the Korean government or any of the listed agencies. Use at your own risk.

---

## πŸ™ Credits & Acknowledgments

The two bus modules in this integration are built on top of work by these open-source projects. Deep thanks to the original authors.

| Module | Author | Source |
|---|---|---|
| 🚍 Korea Bus (`korea_bus/`) | **luiseok** | |
| 🚌 Seoul Bus (`seoul_bus/`) β€” origin | **miumida** | |
| 🚌 Seoul Bus (`seoul_bus/`) β€” patterns | **Murianwind** | |

### What this integration adds on top

The base flows came from the works above. As we absorbed them into the `kr_component_kit` integration pattern, we layered the following on:

- **Single integration for both flows** β€” KakaoMap (Korea Bus) + Seoul official API (Seoul Bus) under one menu
- **Migration safety net** β€” `async_migrate_entry` handles the `kakao_bus` β†’ `korea_bus` domain rename and the `_api_active` β†’ `_update_active` suffix swap so existing users' automations don't break
- **TIMESTAMP-based sensors** β€” HA renders "N min from now" automatically, native to Weather/Calendar UX
- **Stale-data preservation** β€” last successful response stays on the entity during transient API errors
- **Activation switch** (continuing the Murianwind pattern) + **refresh button**
- **Low-floor / Full-bus binary_sensors** (uses Seoul `busType` / `isFullFlag` / `congestion` fields the original wrapper didn't expose)
- **Multi-stop entries + options menu** for add / remove / edit routes without re-registering
- **8 automation blueprints** (departure / alight / lastride / crowded / proximity-toggle / leaving-home / arrival-alight / commute-auto-mode)
- **i18n in 4 languages** (strings + en + ko + ja)

Without the upstream work, this integration wouldn't exist. πŸ™

---

## 🀝 Contributing & License

- **License**: [MIT](LICENSE) β€” free to use, modify, and redistribute
- Issues and PRs welcome:
- Suggestions for new Korean services to add are very welcome

---

## ⭐ Star if useful

A single Star ⭐ at the top right goes a long way. More stars β†’ higher chance of HACS Default Repository acceptance β†’ more Korean users can discover this.

[![Star History Chart](https://api.star-history.com/svg?repos=redchupa/kr_component_kit&type=Date)](https://star-history.com/#redchupa/kr_component_kit&Date)

---

## β˜• Donations

If this saved you time, a coffee would be appreciated πŸ™



Toss (Korean)

Toss donation QR


PayPal

PayPal donation QR

---

**Made with ❀️ for Korean Home Assistant users**

[hacs]: https://github.com/hacs/integration
[hacsbadge]: https://img.shields.io/badge/HACS-Custom-orange.svg?style=for-the-badge
[releases-shield]: https://img.shields.io/github/release/redchupa/kr_component_kit.svg?style=for-the-badge
[releases]: https://github.com/redchupa/kr_component_kit/releases
[commits-shield]: https://img.shields.io/github/commit-activity/y/redchupa/kr_component_kit.svg?style=for-the-badge
[commits]: https://github.com/redchupa/kr_component_kit/commits/main
[license-shield]: https://img.shields.io/github/license/redchupa/kr_component_kit.svg?style=for-the-badge
[stars-shield]: https://img.shields.io/github/stars/redchupa/kr_component_kit.svg?style=for-the-badge
[stars]: https://github.com/redchupa/kr_component_kit/stargazers