Skip to content

Commit de3e680

Browse files
committed
Added higher/lower values to each chart
1 parent d6919c1 commit de3e680

3 files changed

Lines changed: 89 additions & 0 deletions

File tree

‎app/app.py‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,66 @@ def get_sensors():
163163

164164
BASE_URL = 'https://air.siemreap.cloud'
165165

166+
def _aqi_comparison():
167+
"""Query InfluxDB for period-over-period AQI averages.
168+
Returns dict keyed by 'day','week','month' with (direction, delta_pct) tuples.
169+
direction is 'up', 'down', 'similar', or None (insufficient data).
170+
"""
171+
measurement, _ = INFLUX_ENTITIES['aqi']
172+
periods = [
173+
('day', '-24h', '-48h', '-24h'),
174+
('week', '-7d', '-14d', '-7d'),
175+
('month', '-30d', '-60d', '-30d'),
176+
]
177+
results = {}
178+
try:
179+
with InfluxDBClient(url=INFLUX_URL, token=INFLUX_TOKEN, org=INFLUX_ORG) as client:
180+
qapi = client.query_api()
181+
for period, curr_start, prev_start, prev_stop in periods:
182+
curr_q = f'''from(bucket: "{INFLUX_BUCKET}")
183+
|> range(start: {curr_start})
184+
|> filter(fn: (r) => r["_measurement"] == "{measurement}")
185+
|> filter(fn: (r) => r["_field"] == "value")
186+
|> mean()'''
187+
prev_q = f'''from(bucket: "{INFLUX_BUCKET}")
188+
|> range(start: {prev_start}, stop: {prev_stop})
189+
|> filter(fn: (r) => r["_measurement"] == "{measurement}")
190+
|> filter(fn: (r) => r["_field"] == "value")
191+
|> mean()'''
192+
curr_val = next((r.get_value() for t in qapi.query(curr_q) for r in t.records), None)
193+
prev_val = next((r.get_value() for t in qapi.query(prev_q) for r in t.records), None)
194+
if curr_val is None or prev_val is None or prev_val == 0:
195+
results[period] = (None, None)
196+
else:
197+
pct = (curr_val - prev_val) / prev_val * 100
198+
if abs(pct) < 2:
199+
results[period] = ('similar', None)
200+
elif pct > 0:
201+
results[period] = ('up', round(abs(pct)))
202+
else:
203+
results[period] = ('down', round(abs(pct)))
204+
except Exception as e:
205+
app.logger.error(f'AQI comparison error: {e}')
206+
for period, *_ in periods:
207+
results.setdefault(period, (None, None))
208+
return results
209+
210+
166211
@app.route('/metric/<entity_key>/')
167212
def metric(entity_key):
168213
"""Serve the metric history graph page with server-rendered OG tags."""
169214
meta = METRIC_META.get(entity_key, {'label': 'Air Quality', 'description': 'Live air quality readings for Siem Reap, Cambodia.'})
215+
216+
aqi_day_dir = aqi_day_delta = None
217+
aqi_week_dir = aqi_week_delta = None
218+
aqi_month_dir = aqi_month_delta = None
219+
220+
if entity_key == 'aqi':
221+
cmp = _aqi_comparison()
222+
aqi_day_dir, aqi_day_delta = cmp.get('day', (None, None))
223+
aqi_week_dir, aqi_week_delta = cmp.get('week', (None, None))
224+
aqi_month_dir, aqi_month_delta = cmp.get('month', (None, None))
225+
170226
template_path = os.path.join(app.root_path, 'static', 'metric', 'index.html')
171227
with open(template_path) as f:
172228
template_str = f.read()
@@ -176,6 +232,12 @@ def metric(entity_key):
176232
og_description=meta['description'],
177233
og_url=f"{BASE_URL}/metric/{entity_key}/",
178234
og_image=f"{BASE_URL}/images/og-{entity_key}.png",
235+
aqi_day_direction=aqi_day_dir,
236+
aqi_day_delta=aqi_day_delta,
237+
aqi_week_direction=aqi_week_dir,
238+
aqi_week_delta=aqi_week_delta,
239+
aqi_month_direction=aqi_month_dir,
240+
aqi_month_delta=aqi_month_delta,
179241
)
180242

181243

‎app/static/css/metric.css‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ nav {
7777
height: 400px;
7878
}
7979

80+
.comparison-line {
81+
font-size: 0.8rem;
82+
letter-spacing: 0.02em;
83+
margin-bottom: 1rem;
84+
}
85+
8086
/* Desktop height breakpoints — independent of width */
8187

8288
/* Shorter desktop monitors ~1080px tall */

‎app/static/metric/index.html‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ <h1><a href="/">Air Quality Monitor</a></h1>
9090
<span id="mm-low">--</span> &middot; Avg <span id="mm-avg">--</span>
9191
</div>
9292
</div>
93+
{% if aqi_day_direction == 'up' %}
94+
<div class="comparison-line"><span style="color:#ef4444;">▲ {{ aqi_day_delta }}%</span> higher than the past 24h</div>
95+
{% elif aqi_day_direction == 'down' %}
96+
<div class="comparison-line"><span style="color:#22c55e;">▼ {{ aqi_day_delta }}%</span> lower than the past 24h</div>
97+
{% elif aqi_day_direction == 'similar' %}
98+
<div class="comparison-line" style="color:#888;">≈ similar to the past 24h</div>
99+
{% endif %}
93100
<div class="chart-container">
94101
<canvas id="chart"></canvas>
95102
</div>
@@ -103,6 +110,13 @@ <h1><a href="/">Air Quality Monitor</a></h1>
103110
<span id="mm7d-low">--</span> &middot; Avg <span id="mm7d-avg">--</span>
104111
</div>
105112
</div>
113+
{% if aqi_week_direction == 'up' %}
114+
<div class="comparison-line"><span style="color:#ef4444;">▲ {{ aqi_week_delta }}%</span> higher than the past 7d</div>
115+
{% elif aqi_week_direction == 'down' %}
116+
<div class="comparison-line"><span style="color:#22c55e;">▼ {{ aqi_week_delta }}%</span> lower than the past 7d</div>
117+
{% elif aqi_week_direction == 'similar' %}
118+
<div class="comparison-line" style="color:#888;">≈ similar to the past 7d</div>
119+
{% endif %}
106120
<div class="chart-container">
107121
<canvas id="chart7d"></canvas>
108122
</div>
@@ -115,6 +129,13 @@ <h1><a href="/">Air Quality Monitor</a></h1>
115129
High <span id="mm30d-high">--</span> &middot; Low <span id="mm30d-low">--</span> &middot; Avg <span id="mm30d-avg">--</span>
116130
</div>
117131
</div>
132+
{% if aqi_month_direction == 'up' %}
133+
<div class="comparison-line"><span style="color:#ef4444;">▲ {{ aqi_month_delta }}%</span> higher than the past 30d</div>
134+
{% elif aqi_month_direction == 'down' %}
135+
<div class="comparison-line"><span style="color:#22c55e;">▼ {{ aqi_month_delta }}%</span> lower than the past 30d</div>
136+
{% elif aqi_month_direction == 'similar' %}
137+
<div class="comparison-line" style="color:#888;">≈ similar to the past 30d</div>
138+
{% endif %}
118139
<div class="chart-container">
119140
<canvas id="chart30d"></canvas>
120141
</div>

0 commit comments

Comments
 (0)