Rahatara commited on
Commit
5a9b1ce
·
verified ·
1 Parent(s): 98a5ade

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +114 -0
app.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import seaborn as sns
4
+ import matplotlib.pyplot as plt
5
+ import matplotlib.dates as mdates
6
+ import requests, os, json, threading, time
7
+ from datetime import datetime, timedelta
8
+
9
+ CSV_LOG = "baby_log.csv"
10
+ JSON_LOG = "baby_log.json"
11
+ PLOT_PATH = "routine_chart.png"
12
+ PUSHCUT_API_KEY = "rqo6JIF_fytsDlxKWOFrK3Hs" # 👈 replace with real key
13
+ NOTIF_NAME = "Feed Reminder" # must match Pushcut app notification
14
+
15
+ # Load or create log
16
+ if os.path.exists(CSV_LOG):
17
+ log_df = pd.read_csv(CSV_LOG)
18
+ log_df["datetime"] = pd.to_datetime(log_df["datetime"])
19
+ else:
20
+ log_df = pd.DataFrame(columns=["datetime", "event"])
21
+
22
+ def save_logs():
23
+ log_df.to_csv(CSV_LOG, index=False)
24
+ log_df.to_json(JSON_LOG, orient="records", date_format="iso")
25
+
26
+ def parse_time(hour, minute, ampm):
27
+ hour = int(hour)
28
+ minute = int(minute)
29
+ if ampm == "PM" and hour < 12:
30
+ hour += 12
31
+ if ampm == "AM" and hour == 12:
32
+ hour = 0
33
+ now = datetime.now()
34
+ return now.replace(hour=hour, minute=minute, second=0, microsecond=0)
35
+
36
+ def smart_next_feed_time(last_time):
37
+ hour = last_time.hour
38
+ interval = timedelta(hours=4) if hour >= 21 or hour < 10 else timedelta(hours=2)
39
+ return last_time + interval
40
+
41
+ def plot_feeds(df):
42
+ if df.empty:
43
+ return None
44
+ df["hour"] = df["datetime"].dt.hour + df["datetime"].dt.minute / 60
45
+ plt.figure(figsize=(14, 5))
46
+ ax = sns.scatterplot(data=df, x="datetime", y="hour", hue="event", s=120)
47
+ ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %d\n%I:%M %p'))
48
+ plt.ylabel("Hour")
49
+ plt.title("Baby Feeding Routine")
50
+ plt.grid(True)
51
+ plt.tight_layout()
52
+ plt.savefig(PLOT_PATH, bbox_inches='tight')
53
+ return PLOT_PATH
54
+
55
+ def summarize_today(df):
56
+ today = datetime.now().date()
57
+ df["datetime"] = pd.to_datetime(df["datetime"])
58
+ count = df[df["datetime"].dt.date == today].shape[0]
59
+ return f"🍼 Feedings today: {count}"
60
+
61
+ def send_pushcut():
62
+ url = f"https://api.pushcut.io/v1/notifications/{NOTIF_NAME}"
63
+ headers = {"Authorization": f"Bearer {PUSHCUT_API_KEY}", "Content-Type": "application/json"}
64
+ try:
65
+ res = requests.post(url, headers=headers, json={"text": "🍼 Time to feed the baby!"})
66
+ return "✅ Notification sent" if res.status_code == 200 else f"❌ Failed: {res.status_code}"
67
+ except Exception as e:
68
+ return f"❌ Error: {str(e)}"
69
+
70
+ def schedule_notification(feed_time):
71
+ def notify():
72
+ delay = (feed_time - datetime.now()).total_seconds()
73
+ if delay > 0:
74
+ time.sleep(delay)
75
+ send_pushcut()
76
+ threading.Thread(target=notify, daemon=True).start()
77
+
78
+ def log_feeding(hour, minute, ampm):
79
+ global log_df
80
+ feed_time = parse_time(hour, minute, ampm)
81
+ new_entry = pd.DataFrame([{"datetime": feed_time, "event": "Feed"}])
82
+ log_df = pd.concat([log_df, new_entry], ignore_index=True)
83
+ save_logs()
84
+ next_feed = smart_next_feed_time(feed_time)
85
+ schedule_notification(next_feed)
86
+ chart = plot_feeds(log_df)
87
+ summary = summarize_today(log_df)
88
+ return next_feed.strftime("%I:%M %p"), chart, log_df.tail(50).reset_index(drop=True), summary
89
+
90
+ def manual_test_notif(_):
91
+ return send_pushcut()
92
+
93
+ # UI
94
+ with gr.Blocks() as app:
95
+ gr.Markdown("## 👶 Smart Baby Feed Tracker")
96
+ with gr.Row():
97
+ hour = gr.Number(label="Hour", value=10, minimum=1, maximum=12, step=1)
98
+ minute = gr.Number(label="Minute", value=0, minimum=0, maximum=59, step=1)
99
+ ampm = gr.Dropdown(["AM", "PM"], label="AM/PM", value="AM")
100
+ log_btn = gr.Button("✔️ Log Feeding")
101
+
102
+ next_feed_box = gr.Textbox(label="Next Feeding Time")
103
+ chart_output = gr.Image(label="Feeding Chart", type="filepath")
104
+ feed_table = gr.Dataframe(label="Recent Feed Log")
105
+ today_summary = gr.Textbox(label="Today’s Feed Count")
106
+
107
+ log_btn.click(fn=log_feeding, inputs=[hour, minute, ampm], outputs=[next_feed_box, chart_output, feed_table, today_summary])
108
+
109
+ gr.Markdown("### 🔔 Pushcut Test")
110
+ test_btn = gr.Button("Send Test Notification")
111
+ test_result = gr.Textbox()
112
+ test_btn.click(fn=manual_test_notif, inputs=[test_btn], outputs=[test_result])
113
+
114
+ app.launch()