【Python】수면 시간을 toggl에 자동으로 기록하는

Table of Contents
Python을 사용하여 toggl에 수면 시간을 자동으로 기록하는 프로그램을 만듭니다.
개요
자유로운 시간이나 여유로운 시간을 확보하기 위해 여러 작업 관리 도구를 사용하고 있습니다. 주요 도구로 TickTick 등을 사용하며, 완료된 작업 내용을 파악하고 있습니다. 한편, 각각의 작업에 얼마나 시간을 소비했는지 입력량이 명확하지 않다는 점에 주목했습니다.
입력량이 명확하지 않은 점에 대해, toggl이라는 도구를 사용하면 스톱워치처럼 쉽게 시간을 측정하면서 수행한 작업 내용을 빠르게 기록할 수 있습니다. API도 있으므로 자동으로 데이터를 축적할 수도 있습니다. 또한, CSV 출력 기능이 있으므로 데이터를 축적하여 분석할 수 있습니다.
시작으로, 스마트워치에 축적된 수면 시간을 자동으로 toggl에 등록하는 처리를 작성하여 API에 점차 익숙해집니다.
입력 데이터
스마트워치는 Garmin의 Venu 2를 사용합니다.
Garmin은 공식 API를 공개하지 않지만, API를 사용할 수 있는 라이브러리가 존재합니다. 이를 사용하여 수면 로그를 획득하고, toggl API용으로 데이터를 변환합니다. 이번에는 Garmin의 워치를 사용하지만, Fitbit이라면 공식 API도 있습니다.
타사 제품이므로 API에서 반환되는 내용이 다르지만 수면 기록을 획득할 수 있습니다. 수면 시간 기록에 대해, 데이터 획득만 가능하다면 다른 워치도 괜찮을 것 같습니다.
또한, 데이터를 변경하면 수면에 한정되지 않고 다양한 데이터를 입력할 수 있으므로, 다른 API로 운동 시간 등 사람의 작업을 기록하거나, 사람에 한정되지 않고 시간을 기록하는 용도로 사용할 수도 흥미로울 수 있습니다.
코딩
이번에 작성한 코드의 Repository는 다음 URL입니다.
https://github.com/rmc8/Tool-for-transcribing-sleep-records-to-toggl
Main
메인 처리는 main.py에 작성했습니다. YAML 형식의 파일이나 명령줄에서 설정을 가져와 프로그램을 실행합니다.
명령줄은 다음과 같은 구성입니다.
python main.py {되돌아갈 날짜 수}
명령줄에서 되돌아갈 날짜 수에 1
을 입력하면, 프로그램 실행일로부터 전일 범위, 30
을 입력하면 유사하게 30일 전까지의 범위 수면 기록을 한 번에 획득을 시도합니다. 인수를 생략하면 당일 분만 획득을 시도합니다. 날짜 지정이 불가능한 것은 불편할 수 있지만, 작업 스케줄러로 자동 등록하고 끝내고 싶으므로 상당히 간소화했습니다.
YAML 파일은 다음과 같습니다.
time_zone: 9
toggl:
token: # Required
time_entry:
workspace_id:
project_id:
task_id:
billable: False # Not required
tags:
- 수면
garmin:
email: # Required
password: # Required
YAML의 읽기는 util.py에서 PyYAML을 사용하여 구현했습니다. YAML 파일을 딕셔너리 형식으로 읽을 수 있는 편리한 라이브러리입니다. 이 설정 파일의 내용은 모두 API에 전달되는 값입니다. time_zone은 UTC 기준으로 시차가 얼마나 있는지를 입력합니다. 그 외는 후술합니다.
그 후, Garmin의 API에서 수면 시간을 획득하고, toggl용으로 데이터를 변환하여 API를 통해 toggl에 수면 시간을 등록하는 작업을 합니다. 그 후, toggl API로부터의 응답을 ./output
에 CSV 형식으로 출력합니다.
Garmin API
https://github.com/rmc8/Tool-for-transcribing-sleep-records-to-toggl/blob/main/pkg/garmin.py
Garmin으로부터의 데이터 획득은, 앞서 언급한 대로 비공식 라이브러리를 사용합니다. 따라서, 리포지토리의 README나 소스 코드, 개발자 도구를 사용한 분석 외에 데이터 획득의 단서를 얻을 수 없습니다. 소스 코드를 읽으면, Endpoint나 POST 내용도 알 수 있지만, 이번에는 생략합니다.
API 연결
class GarminAPI:
def __init__(self, email: str, password: str, time_deff: int = 9):
self.client = Garmin(email, password)
self.client.login()
self.time_deff: int = time_deff
GarminAPI 클래스를 호출과 동시에 API에 연결합니다. 인증은 Garmin Connect의 사용자 정보와 동일합니다. 이메일 주소와 비밀번호를 config.yml
에 기재합니다. Garmin API로부터의 반환값이 UTC(GMT)이므로, 시차 조정을 위해 일단 time_deff
를 추가했습니다.
수면 로그 획득
get_sleep_logs
메서드를 사용하여 한 번에 수면 정보를 획득합니다. 캡슐화에 의해 숨겨져 있지만, garminconnect 라이브러리에서 제공되는 get_sleep_data
메서드를 사용하면 간단히 수면 시간을 포함한 JSON을 획득할 수 있습니다.
그 JSON의 dailySleepDTO
값에, 취침 시간과 기상 시간을 에포크 초(GMT)형식으로 저장되어 있습니다. 이를 Python의 datetime 형태로 변환하여 시차를 조정하는 작업을 아래에서 수행하고 있습니다.
@staticmethod
def epoc2date(epoc: int, time_deff: int):
dt = datetime.fromtimestamp(epoc / 1000)
return dt + timedelta(hours=time_deff)
start = self.epoc2date(display[“sleepStartTimestampGMT”], self.time_deff)
end = self.epoc2date(display[“sleepEndTimestampGMT”], self.time_deff)
그 후, toggl용으로 데이터를 변환합니다. 딕셔너리의 내용은 다음과 같습니다.
Key | Value | Description |
---|---|---|
date | 잠든 날 | 사용하지 않지만 참고로 |
description | 설명 | 여기서는 언제 잠든지 설명문으로 작성하고 있습니다. |
start | 시작 시간 | 여기서는 취침 시간이 이에 해당합니다. |
stop | 종료 시간 | 여기서는 기상 시간이 이에 해당합니다. |
duration | 경과 시간 | 얼마나 시간이 경과했는지 초 단위로 작성합니다. |
duration
은 toggl의 공식 문서에서 복잡한 설명이 되어 있지만, 아래 그림의 노란색 마커 부분의 표시에 사용됩니다.
마이너스도 가능하다고 잘 모르는 내용도 작성되어 있지만, 이를 적절히 사용하면 수면 시간 중에 잠을 자지 않고 깨어 있었던 시간을 뺀 시간을 입력하는 등의 사용도 가능합니다. 그 외는 특별히 까다로운 것은 아니므로 일단 생략합니다.
모든 날짜를 되돌아가며 수면 시간 등을 요약한 데이터가 완성되면, Pandas의 데이터 프레임 형식으로 변환하여 main.py
에 반환합니다.
toggl API
https://github.com/rmc8/Tool-for-transcribing-sleep-records-to-toggl/blob/main/pkg/toggl.py
toggl API는 GitHub에 요약되어 있습니다. Python 클라이언트도 있지만, PyPI에서 획득할 수 없고 사용법도 소스 코드를 읽지 않으면 모를 것 같아서, 문서를 기반으로 필요한 처리만 직접 작성했습니다.
API의 인증에는 토큰을 사용합니다. Profile 페이지의 아래에 토큰이 있습니다. 이를 config.yml의 toggl > token
에 기재합니다. 그 외, toggl > time_entry
내의 3종류의 ID는 특정 위치에 기록하고 싶은 경우에 기재합니다. billable
은 수면이 직접 이익을 창출하는 것이 아니므로, 기본적으로 False로 좋을 것입니다. 그 외, tags
는 리스트 형식으로 태그를 여러 개 설정할 수 있습니다. 일단의 곳, - 수면
으로 하나의 태그만 설정했습니다.
toggl에 기록하기
create_time_entry
메서드를 사용하면, toggl에 수면 시간을 기록합니다. 필수 값을 중심으로 인수로 가져오며, 그 외는 키워드 인수와 언패킹을 사용하여 필요에 따라 추가할 수 있도록 했습니다.stop
은 필수가 아니지만, duration 주위가 까다로워 stop
이 없으면 종료 시간이 어긋날 수 있으므로, 시간을 명시적으로 입력할 수 있도록 했습니다.
그 후, 문서에 따른 JSON Payload 같은 것이 생성되므로, 이를 _request
메서드에 던져 API를 통해 한 번에 수면 시간을 등록합니다.
로그 출력
./output
디렉터리에 API의 결과를 CSV 형식으로 출력합니다. 샘플은 다음과 같습니다.
id,wid,billable,start,stop,duration,description,tags,duronly,at,uid
2xxxxxxxxx,5xxxxxxxx,False,2021-09-25T23:46:00.000+09:00,2021-09-26T06:56:00.000+09:00,25800,Sleep time on 2021-09-25,[‘수면’],False,2021-09-26T08:59:03+00:00,7xxxxxxxx
미래의 응용
수면 시간을 자동으로 등록할 수 있게 되었습니다. 이와 마찬가지로, 스마트워치나 IoT의 활용으로 자동 등록 가능한 것은 먼저 자동 등록을 진행하고 싶습니다.
TickTick은 GAS나 IFTTT 등을 연동시키면서 중요한 작업은 수동으로 등록하거나 등으로, 할 일을 요약하고 있습니다. 이를 API로 획득하여, 수행 중인 작업을 선택하고 스톱워치를 (시작·중지)·(완료·미완)의 제어가 가능하면, 입력과 출력의 관리가 수월해질 것 같습니다.
그 외, API가 사용되지 않는 부분은 앱의 기능이 매우 간단하므로 그대로 사용하면 작업 관리나 분석이 훨씬 수월해질 것 같습니다.
일반적으로 toggl 앱을 사용하는 것 외에는 아직 코딩이 필요하지만, 있는 것을 재활용하면서 API로 연동할 수 있고, 게다가 클라우드에서 모든 단말기에서 정보 공유도 가능합니다. 개인 이용이라면 무료로 사용하고 필요한 기능 이상이므로 매우 감사합니다.
요약
시간을 관리하고 분석하는 플랫폼으로서 toggl은 매우 좋습니다. 일본어 지원은 아직 부족하지만, 영어에 알레르기가 없다면 매우 유용하고 확장성 높은 도구라고 생각합니다.ぜひ, 다양한 IoT 기기나 API 등과 결합하여 사용해 보세요.