본문 바로가기

위도·경도로 거리 계산하고 위치 기반으로 똑똑한 스마트홈 자동화 구현

728x90

두 위치 좌표 간의 거리를 구하는 방법은 다양한 프로그래밍 언어에서 구현할 수 있으며, 일반적으로 위도(latitude)경도(longitude)를 이용해 지구 곡률을 고려한 거리 계산(Haversine 공식)을 사용합니다. 아래에 개요, 배경, 수학식, 활용사례 및 예시 코드를 포함해 설명드리겠습니다.

📍 기본 개요: 좌표 간 거리 계산

두 지점 A(위도 φ₁, 경도 λ₁)와 B(위도 φ₂, 경도 λ₂)가 주어졌을 때, 이들 사이의 거리를 계산하려면 다음 조건을 고려해야 합니다.

  • 지구는 완벽한 구형이 아니지만, 평균 반지름 6,371 km를 기준으로 계산합니다.
  • 두 점 사이의 거리는 직선 거리(대권거리, great-circle distance)로 구합니다.

🧮 수학적 배경: Haversine 공식

a = sin²(Δφ / 2) + cos(φ₁) × cos(φ₂) × sin²(Δλ / 2)
c = 2 × atan2(√a, √(1−a))
d = R × c
  • Δφ = φ₂ − φ₁ (위도 차이, 라디안 단위)
  • Δλ = λ₂ − λ₁ (경도 차이, 라디안 단위)
  • R = 지구 반지름 (6,371 km 또는 6,371,000 m)
  • d = 두 좌표 사이의 거리

Python 예제 코드

from math import radians, sin, cos, sqrt, atan2

def haversine(lat1, lon1, lat2, lon2):
    R = 6371000  # 지구 반지름 (단위: m)

    # 위도/경도 라디안 변환
    phi1 = radians(lat1)
    phi2 = radians(lat2)
    d_phi = radians(lat2 - lat1)
    d_lambda = radians(lon2 - lon1)

    # Haversine 공식 적용
    a = sin(d_phi / 2) ** 2 + cos(phi1) * cos(phi2) * sin(d_lambda / 2) ** 2
    c = 2 * atan2(sqrt(a), sqrt(1 - a))

    distance = R * c
    return distance  # 단위: meter

# 예: 서울(37.5665, 126.9780) ↔ 부산(35.1796, 129.0756)
print(f"거리: {haversine(37.5665, 126.9780, 35.1796, 129.0756) / 1000:.2f} km")

활용사례

  1. 보안 분야
    • 출입 위치 간 거리를 비교하여 비정상 접근 판단 (예: GPS 위조 탐지)
    • 특정 기기 또는 사용자 이동 경로 분석 (예: 정보 유출 탐지)
  2. 물류/배송
    • 배송 경로 최적화 및 예상 도착 시간 계산
    • 지정 지역 내 여부 판단 (예: 1km 이내 진입 여부)
  3. 생활 서비스 앱
    • 사용자 위치 기반 근처 가맹점 추천
    • 배달 가능 지역 판별
  • 위치정보 수집 시 사전 동의 확보 필요 (개인정보 보호법)
  • 정확한 좌표 보정이 필요한 경우, 실시간 보정 GPS(RTK)나 Wi-Fi 위치 보조 정보 활용
  • 좌표 변환 오류 처리: 위/경도는 도(degree)에서 라디안으로 정확히 변환해야 함
  • 반복 호출 시 서버 부하 주의: 캐시 혹은 사전 거리 계산 방식 적용 권장

추가 도구

  • Python 외 사용 예
    • JavaScript: geolib.getDistance(), turf.js
    • SQL: ST_Distance_Sphere() (MySQL), ST_Distance() + SRID (PostGIS)
  • 도식화: Folium, Leaflet, Google Maps API

Home Assistant에서는 template 센서 또는 template 함수를 이용해 Jinja2 기반 템플릿 코드로 두 지점의 위도/경도 좌표 간 거리 계산이 가능합니다. distance() 함수를 사용하면 복잡한 수식 없이도 간단하게 거리를 구할 수 있습니다.

Home Assistant 템플릿에서 거리 계산하는 방법

📐 기본 함수: distance()

Home Assistant의 Jinja 템플릿 엔진에서는 다음 함수를 제공합니다.

distance(location1, location2)
  • location(위도, 경도) 튜플 형식
  • 반환값: 단위는 킬로미터(KM)

예제 1: 두 좌표 간 거리 계산 (직접 지정)

{{ distance((37.5665, 126.9780), (35.1796, 129.0756)) | round(2) }} km

📌 출력 결과: 서울 ↔ 부산 사이의 대략 거리 (약 325.38 km)

예제 2: 나의 위치 vs 특정 장소

{{ distance(state_attr('device_tracker.my_phone', 'latitude'), state_attr('device_tracker.my_phone', 'longitude'),
            37.5665, 126.9780) | round(1) }}

device_tracker.my_phone의 현재 위치와 서울시청 간 거리 계산

예제 3: template 센서로 등록

template:
  - sensor:
      - name: "집과 회사 거리"
        unit_of_measurement: "km"
        state: >
          {{ distance((state_attr('zone.home', 'latitude'), state_attr('zone.home', 'longitude')),
                      (state_attr('zone.work', 'latitude'), state_attr('zone.work', 'longitude'))) | round(2) }}
  • zone.home, zone.work은 Home Assistant에 등록된 위치 영역
  • 거리 값을 센서 형태로 대시보드에 표시할 수 있습니다

활용 팁

항목 설명
위치정보 노출 템플릿이나 로그에 좌표 직접 노출 시 개인정보 유출 주의
거리에 따른 자동화 특정 거리 이내 진입 시 알림/자동화 가능 (예: distance < 1 km)
Wi-Fi 기반 zone 오차 보정 device_tracker와 zone 간 오차 발생 시 거리 기반 로직이 더 정밀

아이디어

  • 출근 거리 기반 자동화 (거리 < 1km → 조명 켜기)
  • 가족 구성원 도착 거리 알림
  • 차량 GPS 연동 후 이동 경로 추적
  • 특정 위치 벗어나면 알림 전송
300x250

아래는 distance(), as_timestamp(), now() 등의 Jinja 템플릿 함수를 활용한 위치 기반 자동화 템플릿 예시와 함께, Home Assistant의 주요 위치 센서(zone, device_tracker, person) 별로 자동화를 구성하는 활용 사례입니다.

위치 기반 템플릿 함수 조합 개요

함수 설명
distance(loc1, loc2) 위도/경도 또는 zone, entity 속성을 기반으로 거리 계산 (단위: km)
now() 현재 시간 반환 (datetime 객체)
as_timestamp() datetime → timestamp(초) 변환
states('entity_id') entity 상태(예: 'home', 'not_home') 조회
state_attr('entity_id', 'latitude') 특정 entity의 속성 추출

센서별 자동화 사례

1. zone 기반 자동화 예시

목적: "집(zone.home)에 1km 이내 접근 시 조명 켜기"

automation:
  - alias: "가정집 근처 접근 시 조명 켜기"
    trigger:
      - platform: time_pattern
        minutes: "/1"  # 1분마다 평가
    condition:
      - condition: template
        value_template: >
          {{ distance(
            (state_attr('device_tracker.my_phone', 'latitude'), state_attr('device_tracker.my_phone', 'longitude')),
            (state_attr('zone.home', 'latitude'), state_attr('zone.home', 'longitude'))
          ) < 1 }}
    action:
      - service: light.turn_on
        target:
          entity_id: light.living_room

📌 zone.home 좌표 기준으로 device_tracker가 반경 1km 이내로 들어오면 자동 실행

2. device_tracker 기반 자동화 예시

목적: "부재 중일 때 집에 500m 이내 접근하면 알림 전송"

automation:
  - alias: "집 근처 접근 시 알림"
    trigger:
      - platform: state
        entity_id: device_tracker.my_phone
        to: 'not_home'
        for: "00:05:00"
    condition:
      - condition: template
        value_template: >
          {{ distance(
            (state_attr('device_tracker.my_phone', 'latitude'), state_attr('device_tracker.my_phone', 'longitude')),
            (state_attr('zone.home', 'latitude'), state_attr('zone.home', 'longitude'))
          ) < 0.5 }}
    action:
      - service: notify.mobile_app_myphone
        data:
          message: "집 근처입니다. 자동문 열까요?"

3. person 센서 기반 자동화 예시

person은 여러 device_tracker를 통합한 고수준 엔터티입니다.

목적: "사람이 회사에서 퇴근하면 자동으로 보일러 끄기 (퇴근 시간 + 위치)"

automation:
  - alias: "퇴근 시 보일러 OFF"
    trigger:
      - platform: state
        entity_id: person.john
        from: 'work'
        to: 'not_home'
    condition:
      - condition: time
        after: "17:30:00"
    action:
      - service: climate.turn_off
        target:
          entity_id: climate.home_heater

4. 시간 + 위치 기반 템플릿 (거리 + 이동시간 평가)

목적: "지금 위치에서 집까지 거리 3km 이상이고, 저녁 10시 이후면 '귀가 중' 알림 전송"

trigger:
  - platform: time_pattern
    minutes: "/5"  # 5분마다 실행

condition:
  - condition: template
    value_template: >
      {% set dist = distance(
        (state_attr('device_tracker.my_phone', 'latitude'), state_attr('device_tracker.my_phone', 'longitude')),
        (state_attr('zone.home', 'latitude'), state_attr('zone.home', 'longitude'))
      ) %}
      {% set hour = now().hour %}
      {{ dist > 3 and hour >= 22 }}

action:
  - service: notify.mobile_app_myphone
    data:
      message: "밤 늦게 집에 가는 중이군요. 조심히 들어가세요!"

사용자 관리

항목 점검 포인트
위치 추적 범위 제한 너무 자주 distance() 호출 시 서버 부하 가능 → 1~5분 주기 권장
개인정보 보호 GPS 좌표는 로그 및 UI에 노출되지 않도록 주의
다중 사용자 추적 person.john, person.jane 식으로 구분하여 자동화 별도 설정
geo_location 연계 외부 이벤트(ex: 특정 지역 위험 알림)와 거리 기준 조건 연동 가능

유형 정리

구성요소 활용 함수 자동화 예시
zone state_attr('zone.name', 'latitude') 특정 장소 반경 내 접근 감지
device_tracker distance(), state_attr() 실시간 거리 기반 판단
person state == 'home', not_home 통합 위치 상태 기반 조치
시간 조건 now(), as_timestamp() 특정 시간대 조건 결합
728x90
그리드형(광고전용)

댓글