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.
- Host: GitHub
- URL: https://github.com/redchupa/kr_component_kit
- Owner: redchupa
- License: mit
- Created: 2026-04-17T09:50:15.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-05-17T22:41:35.000Z (about 1 month ago)
- Last Synced: 2026-05-17T22:44:51.372Z (about 1 month ago)
- Topics: custom-component, custom-components, hacs, hacs-integration, home-assistant, home-automation, homeassistant, kepco, korea, korean, smart-home
- Language: Python
- Size: 1.19 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.en.md
- Funding: .github/FUNDING.yml
- License: LICENSE
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]
[](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.
[](https://star-history.com/#redchupa/kr_component_kit&Date)
---
## β Donations
If this saved you time, a coffee would be appreciated π
Toss (Korean)
PayPal
---
**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