9.16. 시간과 NTP

방금 전원을 켠 카메라는 현재 시각이 몇 시인지 전혀 알지 못합니다. 온보드 시계는 임의의 시점(대부분의 보드에서는 1970-01-01)에서 시작하여, 다른 무언가가 바로잡아 주기 전까지 그 시점부터 시간을 세어 나갑니다. NTP – Network Time Protocol – 는 카메라가 네트워크에 실제 벽시계 시각을 물어보고 그 응답을 바탕으로 자신의 시계를 설정하는 방법입니다.

9.16.1. 카메라가 시간을 알아야 하는 이유

많은 스크립트에서는 카메라의 시계가 중요하지 않습니다. 프레임 캡처 루프는 오늘이 며칠인지 신경 쓰지 않습니다. 그러나 몇 가지 일반적인 경우에는 시간이 매우 중요합니다:

  • 로그나 업로드된 데이터의 타임스탬프. 모든 항목이 1970-01-01로 표시되어 있으면 나중에 의미를 파악하기 어렵습니다.

  • 예약된 작업. “03:00에 실행”하려면 카메라가 03:00이 언제인지 알아야 합니다.

9.16.2. NTP가 하는 일

NTP는 작은 공용 서비스입니다. 단일 UDP 교환으로 “지금 몇 시입니까?”에 응답하는 서버 네트워크죠. 카메라는 알려진 NTP 서버로 짧은 요청을 보내고, 서버는 정밀한 타임스탬프(일반적인 공용 서버라면 수 밀리초 단위로 정확함)로 응답하며, 카메라는 이를 사용해 자신의 시계를 설정합니다. 카메라가 기본으로 사용하는 서버는 pool.ntp.org로, 바로 이런 종류의 클라이언트를 위해 설계된 전 세계적으로 부하 분산되는 풀입니다.

9.16.3. Python API: ntptime

MicroPython은 이 프로토콜을 하나의 호출로 감쌉니다. 일반적인 패턴은 먼저 링크를 올린 다음 NTP에 시간을 요청하는 것입니다:

import network
import ntptime
import time

wlan = network.WLAN(network.WLAN.IF_STA)
wlan.active(True)
wlan.connect("my-network", "my-password")

while not wlan.isconnected():
    time.sleep_ms(100)

ntptime.settime()                 # cam's clock is now UTC
print(time.localtime())

ntptime.settime()가 반환된 후에는 온보드 실시간 클록과 time.localtime()이 현재 UTC 시간을 반영합니다. 기본값을 조정하는 두 가지 설정이 있습니다:

  • ntptime.host는 질의할 서버 이름입니다. settime()를 호출하기 전에 이를 재정의(ntptime.host = "time.google.com")하면 다른 서버를 가리키게 할 수 있습니다.

  • ntptime.timeout은 포기하기 전에 응답을 기다리는 시간(초)입니다. 기본값은 짧습니다.

9.16.4. 언제 호출할 것인가

  • 네트워크 링크가 올라온 후. NTP는 UDP 위에서 동작하고, UDP는 확립된 IP 설정 위에서 동작합니다. 먼저 isconnected()True를 반환할 때까지 기다리세요.

  • 장시간 동작하는 카메라에서는 주기적으로. 온보드 시계는 시간과 날이 지나면서 표류합니다. 매일 또는 매주 settime()를 호출하면 시계를 정확하게 유지할 수 있습니다.

9.16.5. 시간대

NTP는 UTC를 반환합니다. MicroPython은 시간대 데이터베이스를 제공하지 않으므로 UTC를 현지 시간으로 변환하는 것은 스크립트의 몫입니다. 배포 지역의 시간대에 대한 고정 오프셋을 사용하는 것이 일반적인 방법입니다:

import time

offset = -5 * 3600                  # hours -> seconds, US Eastern
local = time.localtime(time.time() + offset)
print(local)

이 방식은 일광 절약 시간제(서머타임), 윤초, 과거의 시간대 변경을 처리하지 않습니다. 대부분의 카메라 배포에서는 고정 오프셋으로 충분합니다. 스크립트가 정말로 일광 절약 시간제가 적용된 시민 시간을 필요로 한다면 변환을 서버 측에서 수행하세요.

9.16.6. 무엇이 잘못될 수 있는가

  • 아직 네트워크가 없음. ntptime.settime()는 서버에 도달할 수 없으면 OSError를 발생시킵니다. 링크가 올라오지 않았거나, 이름 조회에 실패했거나, 서버에 도달할 수 없거나, ntptime.timeout 안에 응답이 도착하지 않은 경우입니다. 링크가 안정되면 다시 시도하세요.

  • 캡티브 포털. DNS를 가로채는 Wi-Fi 네트워크는 NTP 서버 이름에 대해 포털 자체의 IP로 응답할 수 있으며, 그곳으로 보낸 NTP 요청은 의미 없는 결과를 반환합니다. 카메라는 네트워크가 올라왔다고 생각하지만 시간 설정은 실패하거나 크게 어긋나게 됩니다. 깨끗한 네트워크로 옮기거나 IP를 하드코딩하세요.

  • 공용 풀에 과도하게 요청하기. 공용 NTP 풀은 남용하는 클라이언트의 속도를 제한합니다. 시간당 한 번이면 충분하며, 분당 한 번이면 카메라가 차단됩니다.

ntptime의 전체 참조는 ntptime — 간단한 NTP 클라이언트를 참조하세요.