forked from dsutanto/zenai-kpc-python
update untuk penyesuaian mulai hitung saat menerima pesan dari tombol
This commit is contained in:
1 parent
41c4a558b1
commit
3c30ded269
7 files changed
+471
-99
No files matched your search
+70
-8
@@ -139,6 +139,20 @@ CONTROL_SOCKET_ENABLED = os.getenv("CONTROL_SOCKET_ENABLED", "false").lower() ==
|
||||
CONTROL_SOCKET_HOST = os.getenv("CONTROL_SOCKET_HOST", "127.0.0.1")
|
||||
CONTROL_SOCKET_PORT = int(os.getenv("CONTROL_SOCKET_PORT", "5090"))
|
||||
|
||||
# --- Status webhook gate (direction-locked when IN or OUT) ---
|
||||
# When enabled, counting runs only while status is IN or OUT, and only that
|
||||
# direction is counted (IN → in crossings, OUT → out crossings). OFF pauses all.
|
||||
STATUS_WEBHOOK_ENABLED = os.getenv("STATUS_WEBHOOK_ENABLED", "false").lower() == "true"
|
||||
STATUS_WEBHOOK_FILE = os.getenv(
|
||||
"STATUS_WEBHOOK_FILE",
|
||||
"/opt/zenai-kpc-python/status_webhook_state",
|
||||
)
|
||||
_active_raw = os.getenv("STATUS_WEBHOOK_ACTIVE_VALUES", "IN,OUT")
|
||||
STATUS_WEBHOOK_ACTIVE_VALUES = frozenset(
|
||||
part.strip().upper() for part in _active_raw.split(",") if part.strip()
|
||||
)
|
||||
STATUS_WEBHOOK_INACTIVE_VALUE = os.getenv("STATUS_WEBHOOK_INACTIVE_VALUE", "OFF").strip().upper()
|
||||
|
||||
CROSS_FLASH_FRAMES = 12
|
||||
POPUP_LIFETIME = 20
|
||||
LINE_PULSE_FRAMES = 12
|
||||
@@ -750,6 +764,21 @@ def read_counting_flag(default=True):
|
||||
return default
|
||||
|
||||
|
||||
def read_status_webhook():
|
||||
"""Return normalized status from webhook file, or inactive value on error."""
|
||||
try:
|
||||
with open(STATUS_WEBHOOK_FILE, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
status = str(data.get("status", "")).strip().upper()
|
||||
return status or STATUS_WEBHOOK_INACTIVE_VALUE
|
||||
except Exception:
|
||||
return STATUS_WEBHOOK_INACTIVE_VALUE
|
||||
|
||||
|
||||
def status_webhook_allows_counting(status):
|
||||
return status in STATUS_WEBHOOK_ACTIVE_VALUES
|
||||
|
||||
|
||||
def write_control_file(counting):
|
||||
"""Create/update the control file atomically (used to seed defaults)."""
|
||||
try:
|
||||
@@ -1221,6 +1250,8 @@ def run():
|
||||
last_snapshot_cleanup = 0.0
|
||||
|
||||
counting_active = True
|
||||
status_nyala_active = True
|
||||
status_webhook_value = STATUS_WEBHOOK_INACTIVE_VALUE
|
||||
last_control_poll = 0.0
|
||||
control_socket = None
|
||||
if CONTROL_ENABLED:
|
||||
@@ -1236,6 +1267,13 @@ def run():
|
||||
control_socket = start_control_socket()
|
||||
except Exception as exc:
|
||||
print(f"[{now_str()}] Failed to start control socket: {exc}")
|
||||
if STATUS_WEBHOOK_ENABLED:
|
||||
status_webhook_value = read_status_webhook()
|
||||
status_nyala_active = status_webhook_allows_counting(status_webhook_value)
|
||||
print(
|
||||
f"Status webhook enabled | file={STATUS_WEBHOOK_FILE} | "
|
||||
f"status={status_webhook_value}"
|
||||
)
|
||||
|
||||
cap, w, h, fps = connect_stream(SOURCE)
|
||||
if cap is None:
|
||||
@@ -1288,15 +1326,30 @@ def run():
|
||||
cross_events_frame = []
|
||||
detect_events_frame = []
|
||||
|
||||
if CONTROL_ENABLED and (now - last_control_poll) >= CONTROL_POLL_SEC:
|
||||
if (CONTROL_ENABLED or STATUS_WEBHOOK_ENABLED) and (
|
||||
now - last_control_poll
|
||||
) >= CONTROL_POLL_SEC:
|
||||
last_control_poll = now
|
||||
new_flag = read_counting_flag(CONTROL_DEFAULT_COUNTING)
|
||||
if new_flag != counting_active:
|
||||
counting_active = new_flag
|
||||
print(f"[{now_str()}] Counting {'RESUMED' if counting_active else 'PAUSED'} via control file")
|
||||
if CONTROL_ENABLED:
|
||||
new_flag = read_counting_flag(CONTROL_DEFAULT_COUNTING)
|
||||
if new_flag != counting_active:
|
||||
counting_active = new_flag
|
||||
print(
|
||||
f"[{now_str()}] Counting "
|
||||
f"{'RESUMED' if counting_active else 'PAUSED'} via control file"
|
||||
)
|
||||
if STATUS_WEBHOOK_ENABLED:
|
||||
new_status = read_status_webhook()
|
||||
if new_status != status_webhook_value:
|
||||
status_webhook_value = new_status
|
||||
status_nyala_active = status_webhook_allows_counting(
|
||||
status_webhook_value
|
||||
)
|
||||
print(f"[{now_str()}] Status webhook {status_webhook_value}")
|
||||
|
||||
counting_allowed = counting_active and status_nyala_active
|
||||
skip_inference = False
|
||||
if not counting_active:
|
||||
if not counting_allowed:
|
||||
skip_inference = True
|
||||
elif MOTION_DETECTION_ENABLED:
|
||||
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||
@@ -1450,6 +1503,12 @@ def run():
|
||||
# Prefer decisive motion if both count triggers fire in one jump.
|
||||
count_in = in_down and not st["counted"]
|
||||
count_out = out_up and not st["counted"]
|
||||
if STATUS_WEBHOOK_ENABLED:
|
||||
# Webhook IN → only IN counts; OUT → only OUT counts.
|
||||
if status_webhook_value == "IN":
|
||||
count_out = False
|
||||
elif status_webhook_value == "OUT":
|
||||
count_in = False
|
||||
if count_in and count_out:
|
||||
if cy >= prev_cy:
|
||||
count_out = False
|
||||
@@ -1586,8 +1645,11 @@ def run():
|
||||
)
|
||||
popups = draw_popups(frame, popups, frame_idx)
|
||||
|
||||
if CONTROL_ENABLED and not counting_active:
|
||||
badge = "COUNTING PAUSED"
|
||||
if (CONTROL_ENABLED or STATUS_WEBHOOK_ENABLED) and not counting_allowed:
|
||||
if STATUS_WEBHOOK_ENABLED and not status_nyala_active:
|
||||
badge = status_webhook_value
|
||||
else:
|
||||
badge = "COUNTING PAUSED"
|
||||
(bw, bh), _ = cv2.getTextSize(badge, cv2.FONT_HERSHEY_SIMPLEX, 0.6, 2)
|
||||
bx = w // 2 - bw // 2
|
||||
overlay_rect(frame, bx - 14, 48, bx + bw + 14, 48 + bh + 18, C_PANEL, alpha=0.75)
|
||||
|
||||
Reference in new issue
Block a user