Files
Garmin-API/app.py
T
2026-03-31 08:17:07 +01:00

140 lines
3.4 KiB
Python

from flask import Flask, jsonify, send_file
import datetime
import os
import time
from garminconnect import Garmin
app = Flask(__name__)
# --- CONFIG ---
EMAIL = os.getenv("GARMIN_EMAIL")
PASSWORD = os.getenv("GARMIN_PASSWORD")
START_DATE = datetime.date.fromisoformat(os.getenv("START_DATE", "2026-01-01"))
GOAL_KM = float(os.getenv("GOAL_KM", "80"))
ALLOWED_TYPES = os.getenv("ALLOWED_TYPES", "running,treadmill_running").split(",")
CACHE_TTL = int(os.getenv("CACHE_TTL", "300")) # seconds (default 5 mins)
# --- GLOBAL CACHE ---
garmin_client = None
last_login_time = 0
cached_data = None
last_fetch_time = 0
def get_client():
global garmin_client, last_login_time
# Reuse client if already logged in
if garmin_client:
return garmin_client
# Otherwise login once
garmin_client = Garmin(EMAIL, PASSWORD)
garmin_client.login()
last_login_time = time.time()
print("✅ Logged into Garmin")
return garmin_client
def get_garmin_data():
global cached_data, last_fetch_time
now = time.time()
# --- RETURN CACHED DATA ---
if cached_data and (now - last_fetch_time < CACHE_TTL):
print("⚡ Returning cached data")
return cached_data
try:
client = get_client()
today = datetime.date.today()
activities = client.get_activities_by_date(
START_DATE.isoformat(), today.isoformat()
)
total_meters = 0
for act in activities:
activity_type = act.get("activityType", {}).get("typeKey", "").lower()
if activity_type in ALLOWED_TYPES:
total_meters += act.get("distance", 0)
total_km = total_meters / 1000.0
result = {
"total_km": round(total_km, 2),
"goal_km": GOAL_KM,
"percent": round((total_km / GOAL_KM) * 100, 1),
"status": "success",
}
# --- UPDATE CACHE ---
cached_data = result
last_fetch_time = now
print("🔄 Fetched fresh data")
return result
except Exception as e:
# If Garmin session expired → reset client and retry once
print(f"⚠️ Error: {e}, retrying login...")
try:
reset_client()
client = get_client()
today = datetime.date.today()
activities = client.get_activities_by_date(
START_DATE.isoformat(), today.isoformat()
)
total_meters = sum(
act.get("distance", 0)
for act in activities
if act.get("activityType", {}).get("typeKey", "").lower() in ALLOWED_TYPES
)
total_km = total_meters / 1000.0
result = {
"total_km": round(total_km, 2),
"goal_km": GOAL_KM,
"percent": round((total_km / GOAL_KM) * 100, 1),
"status": "success",
}
cached_data = result
last_fetch_time = now
return result
except Exception as e2:
return {"status": "error", "message": str(e2)}
def reset_client():
global garmin_client
garmin_client = None
print("♻️ Garmin client reset")
@app.route('/progress')
def progress():
return jsonify(get_garmin_data())
@app.route('/image')
def get_image():
return send_file("logo.bin", mimetype='application/octet-stream')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)