adjust api for newest karung admin

This commit is contained in:
Alberto-Audrix committed 2026-08-28 10:58:13 +07:00
1 parent 5b4d9d56d4
commit d7d268ad48
4 files changed
+38 -19

No files matched your search

+3
View File
@@ -3,6 +3,9 @@ __pycache__/
*.py[codz]
*$py.class
#superpower
docs
# C extensions
*.so
+10 -2
View File
@@ -183,6 +183,7 @@ def api_snapshot_image(category, filename):
def _ensure_db():
Path(DB_PATH).parent.mkdir(parents=True, exist_ok=True)
conn = sqlite3.connect(DB_PATH)
cur = conn.cursor()
cur.execute(
@@ -362,7 +363,7 @@ def _empty_counts():
def _empty_current():
return {
"counting_date": get_counting_date(),
"count": 0,
"total_count": 0,
"counts": _empty_counts(),
"zones": ZONES_META,
"start_time": None,
@@ -390,9 +391,16 @@ def _load_current_state():
"zone_2": int(data.get("count_right", 0) or 0),
}
counts = _normalize_counts(counts)
# Prefer total_count; fall back to legacy "count" then sum of zones.
if data.get("total_count") is not None:
total = int(data.get("total_count") or 0)
elif data.get("count") is not None:
total = int(data.get("count") or 0)
else:
total = sum(counts.values())
return {
"counting_date": data.get("counting_date") or get_counting_date(),
"count": int(data.get("count", sum(counts.values())) or 0),
"total_count": total,
"counts": counts,
"zones": ZONES_META,
"start_time": data.get("start_time"),
+9 -8
View File
@@ -177,7 +177,8 @@ class CounterStore:
# Preserve migrated zone_2 even if current config is 1 zone? Spec says
# configured ids only — drop unknown keys from active counts.
state['counts'] = normalized
state['count'] = sum(normalized.values())
state['total_count'] = sum(normalized.values())
state.pop('count', None)
state.pop('count_left', None)
state.pop('count_right', None)
state.setdefault('counted_event_ids', [])
@@ -208,7 +209,7 @@ class CounterStore:
)
state['counted_event_ids'] = []
self.log(
f"Resumed {current_date} with total={state['count']} "
f"Resumed {current_date} with total={state['total_count']} "
f"counts={state['counts']}"
)
with open(self.state_file, 'w', encoding='utf-8') as f:
@@ -236,7 +237,7 @@ class CounterStore:
counts = self._empty_counts()
self.current_state = {
'counting_date': counting_date,
'count': 0,
'total_count': 0,
'counts': counts,
'start_time': now,
'last_detection_time': now,
@@ -264,7 +265,7 @@ class CounterStore:
counted = False
event_key = f"{track_id}_{zone_id}"
if event_key not in self.current_state['counted_event_ids']:
self.current_state['count'] += 1
self.current_state['total_count'] += 1
self.current_state['counts'][zone_id] = (
int(self.current_state['counts'].get(zone_id, 0)) + 1
)
@@ -272,14 +273,14 @@ class CounterStore:
counted = True
self.log(
f'Counted {zone_id} (track {track_id}) | {counting_date} '
f'total: {self.current_state["count"]} '
f'total: {self.current_state["total_count"]} '
f'counts={self.current_state["counts"]}'
)
self._persist_day()
self.current_state['last_detection_time'] = datetime.now().isoformat()
self.save_state()
return self.current_state['count'], day_started, counted
return self.current_state['total_count'], day_started, counted
def _persist_day(self):
state = self.current_state
@@ -298,7 +299,7 @@ class CounterStore:
""",
(
state['counting_date'], self.camera_name, self.object_label,
state['count'],
state['total_count'],
state['start_time'], datetime.now().isoformat(),
),
)
@@ -339,7 +340,7 @@ class CounterStore:
def current_count(self):
if self.current_state is None:
return 0
return self.current_state['count']
return self.current_state['total_count']
@property
def current_counts(self):
+16 -9
View File
@@ -772,8 +772,9 @@
<div class="footer">Edge Nano Counter by ZenAi</div>
</div>
<script type="application/json" id="zones-config">{{ zones | tojson }}</script>
<script>
const ZONES = {{ zones | tojson }};
const ZONES = JSON.parse(document.getElementById('zones-config').textContent);
const ZONE_COLORS = [
['rgba(0, 255, 136, 0.7)', 'rgba(0, 255, 136, 1)'],
['rgba(255, 45, 120, 0.7)', 'rgba(255, 45, 120, 1)'],
@@ -883,7 +884,9 @@ async function loadCurrentCounter() {
if (!res.ok) throw new Error('No active counter');
const data = await res.json();
const counts = data.counts || {};
const total = data.count != null ? data.count : Object.values(counts).reduce((a, b) => a + (b || 0), 0);
const total = data.total_count != null
? data.total_count
: Object.values(counts).reduce((a, b) => a + (b || 0), 0);
document.getElementById('today-count').textContent = total.toLocaleString();
ZONES.forEach(z => {
const el = document.getElementById('today-' + z.id);
@@ -902,12 +905,16 @@ async function loadSummary() {
try {
const res = await fetch('/api/summary');
const data = await res.json();
if (!data || !data.today) {
console.error('Failed to load summary: unexpected payload', data);
return;
}
document.getElementById('current-date').textContent = data.today.date;
document.getElementById('current-date').textContent = data.today.date || '--';
const yCounts = (data.yesterday && data.yesterday.counts) || {};
document.getElementById('yesterday-count').textContent = (
data.yesterday.total_count != null
data.yesterday && data.yesterday.total_count != null
? data.yesterday.total_count
: Object.values(yCounts).reduce((a, b) => a + (b || 0), 0)
).toLocaleString();
@@ -916,14 +923,14 @@ async function loadSummary() {
if (el) el.textContent = (yCounts[z.id] || 0).toLocaleString();
});
document.getElementById('avg-count').textContent = Number(data.average_per_day).toLocaleString();
document.getElementById('total-days').textContent = `${data.all_time.total_days} days recorded`;
document.getElementById('avg-count').textContent = Number(data.average_per_day || 0).toLocaleString();
document.getElementById('total-days').textContent = `${(data.all_time && data.all_time.total_days) || 0} days recorded`;
document.getElementById('best-count').textContent = data.best_day.count.toLocaleString();
document.getElementById('best-date').textContent = data.best_day.date || '--';
document.getElementById('best-count').textContent = ((data.best_day && data.best_day.count) || 0).toLocaleString();
document.getElementById('best-date').textContent = (data.best_day && data.best_day.date) || '--';
const gCounts = (data.all_time && data.all_time.counts) || {};
document.getElementById('grand-total').textContent = (data.all_time.grand_total || 0).toLocaleString();
document.getElementById('grand-total').textContent = ((data.all_time && data.all_time.grand_total) || 0).toLocaleString();
ZONES.forEach(z => {
const el = document.getElementById('grand-' + z.id);
if (el) el.textContent = (gCounts[z.id] || 0).toLocaleString();