update api configuration for panel iot and adjust ai insight

This commit is contained in:
Alberto-Audrix committed 2026-09-18 16:06:41 +07:00
1 parent a2b5b10977
commit 20d04acb3e
20 files changed
+814 -177

No files matched your search

+56 -29
View File
@@ -164,12 +164,21 @@ class SyncSummary:
class IotApiClient:
def __init__(self, base_url: str | None = None, timeout: float | None = None):
self.base_url = (base_url or settings.IOT_API_BASE_URL).rstrip("/") + "/"
def __init__(self, base_url: str, timeout: float | None = None):
self.base_url = (base_url or "").strip()
if not self.base_url:
raise IotApiError("IoT API URL is empty")
self.timeout = timeout or settings.IOT_API_SYNC_TIMEOUT_SECONDS
def fetch_page(self, page: int) -> dict[str, Any]:
url = f"{self.base_url}?page={page}"
from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit
parts = urlsplit(self.base_url)
query = dict(parse_qsl(parts.query, keep_blank_values=True))
query["page"] = str(page)
url = urlunsplit(
(parts.scheme, parts.netloc, parts.path, urlencode(query), parts.fragment)
)
try:
with httpx.Client(timeout=self.timeout) as client:
response = client.get(url)
@@ -183,32 +192,19 @@ class IotApiClient:
return response.json()
def sync_iot_panels(
def _sync_flock_pages(
flock: Flock,
*,
lookback_minutes: int | None = None,
max_pages: int | None = None,
lookback_minutes: int,
max_pages: int,
cutoff,
) -> SyncSummary:
flock_map: dict[str, int] = getattr(settings, "IOT_FLOCK_ID_MAP", {}) or {}
if not flock_map:
return SyncSummary(upserted=0, skipped=0, pages=0)
lookback = lookback_minutes if lookback_minutes is not None else settings.IOT_SYNC_LOOKBACK_MINUTES
page_limit = max_pages if max_pages is not None else settings.IOT_SYNC_MAX_PAGES
cutoff = timezone.now() - timedelta(minutes=lookback)
django_flocks: dict[str, Flock] = {}
for external_id, django_id in flock_map.items():
try:
django_flocks[str(external_id)] = Flock.objects.select_related("kandang").get(pk=int(django_id))
except Flock.DoesNotExist:
continue
client = IotApiClient()
client = IotApiClient(flock.iot_api_url)
upserted = 0
skipped = 0
pages_read = 0
for page in range(1, page_limit + 1):
for page in range(1, max_pages + 1):
payload = client.fetch_page(page)
pages_read += 1
results = payload.get("results") or []
@@ -217,12 +213,6 @@ def sync_iot_panels(
page_has_recent = False
for record in results:
external_flock_id = str(record.get("flock_id") or "")
flock = django_flocks.get(external_flock_id)
if flock is None:
skipped += 1
continue
fetched_raw = record.get("fetched_at")
payload_data = (record.get("payload") or {}).get("data")
if not fetched_raw or not payload_data:
@@ -262,3 +252,40 @@ def sync_iot_panels(
break
return SyncSummary(upserted=upserted, skipped=skipped, pages=pages_read)
def sync_iot_panels(
*,
flock_id: int | None = None,
lookback_minutes: int | None = None,
max_pages: int | None = None,
) -> SyncSummary:
lookback = lookback_minutes if lookback_minutes is not None else settings.IOT_SYNC_LOOKBACK_MINUTES
page_limit = max_pages if max_pages is not None else settings.IOT_SYNC_MAX_PAGES
cutoff = timezone.now() - timedelta(minutes=lookback)
flocks = Flock.objects.select_related("kandang").exclude(iot_api_url="")
if flock_id is not None:
flocks = flocks.filter(pk=flock_id)
flock_list = list(flocks)
if not flock_list:
return SyncSummary(upserted=0, skipped=0, pages=0)
upserted = 0
skipped = 0
pages_read = 0
for flock in flock_list:
if not (flock.iot_api_url or "").strip():
continue
summary = _sync_flock_pages(
flock,
lookback_minutes=lookback,
max_pages=page_limit,
cutoff=cutoff,
)
upserted += summary.upserted
skipped += summary.skipped
pages_read += summary.pages
return SyncSummary(upserted=upserted, skipped=skipped, pages=pages_read)