Defect-Detection / utils.py
Navy
change video stream to base64
ae00b72
import logging, sys, asyncio, random, json, requests, os
from pathlib import Path
from dotenv import load_dotenv
# ============================================================
# LOGGER SETUP
# ============================================================
logger = logging.getLogger("ai_engine_dummy")
logger.setLevel(logging.INFO)
# Handler untuk tampil di console
handler = logging.StreamHandler(sys.stdout)
formatter = logging.Formatter("[%(asctime)s] %(levelname)s → %(message)s", "%H:%M:%S")
handler.setFormatter(formatter)
logger.addHandler(handler)
# ============================================================
# HELPER FUNCTION (opsional untuk simulasi delay)
# ============================================================
async def async_sleep_random(min_s=0.2, max_s=0.8):
"""
Helper untuk simulasi waktu inferensi secara acak.
"""
durasi = random.uniform(min_s, max_s)
await asyncio.sleep(durasi)
# ==============================================================
# VALIDATION FUNCTION
# ==============================================================
def validate_input(required_parts_fields, station_id, cameras, parts, webhook_url):
errors = []
# Validate station_id
if not station_id or not str(station_id).strip():
errors.append("station_id is missing or empty")
# Validate parts
for field in required_parts_fields:
if field not in parts or not str(parts[field]).strip():
errors.append(f"parts.{field} is missing or empty")
# Validate cameras list
if not isinstance(cameras, list) or len(cameras) == 0:
errors.append("cameras must be a non-empty list")
else:
for index, cam in enumerate(cameras):
if "camera_id" not in cam or not str(cam["camera_id"]).strip():
errors.append(f"camera[{index}].camera_id missing or empty")
if "image_base64" not in cam or not str(cam["image_base64"]).strip():
errors.append(f"camera[{index}].image_base64 missing or empty")
# if "rtsp_url" not in cam or not str(cam["rtsp_url"]).strip():
# errors.append(f"camera[{index}].rtsp_url missing or empty")
# Validate webhook
if not webhook_url or not webhook_url.startswith("http"):
errors.append("webhook_url is invalid or missing")
return errors
# ============================================================
# HELPER
# ============================================================
def _metadata():
"""
load file metadata.json into json data
"""
path = Path("metadata/product.json")
if not path.exists():
return {"status": "error", "message": "metadata.json not found"}
with open(path, "r") as f:
data = json.load(f)
return data
def _color_map():
path = Path("metadata/defect.json")
if not path.exists():
return []
with open(path, "r") as f:
return json.load(f)
def model_by_id_metadata(part_id):
"""
part_id = "4" # id part / product
get model_path from metadata by part_id
"""
metadata = _metadata()
id_part = part_id
item = next((x for x in metadata if x["id"] == id_part), None)
model_path = item['model_path']
return model_path
def model_by_pin_metadata(pin_api):
"""
pin_api = "JI4ACL-GCSBYHBK03" # PIN API from part / product
get model_path from metadata by pin_api
"""
metadata = _metadata()
pin_api = pin_api
item = next((x for x in metadata if x["pin_api"] == pin_api), None)
model_path = item['model_path']
return model_path
def color_defect(defect_name):
"""
Return BGR tuple color for OpenCV bounding box.
"""
defect_name = defect_name.lower()
data = _color_map()
item = next((x for x in data if x["class"].lower() == defect_name), None)
if item is None:
return (0, 255, 0) # Default GREEN jika tidak ditemukan
hex_color = item["color"].lstrip('#')
r = int(hex_color[0:2], 16)
g = int(hex_color[2:4], 16)
b = int(hex_color[4:6], 16)
return (b, g, r) # Convert to BGR
def load_json(path):
with open(path, "r") as f:
return json.load(f)
def start_detection(base_url, payload):
return requests.post(f"{base_url}/start-detection", json=payload)
def load_config():
load_dotenv()
return os.getenv("BASE_URL"), os.getenv("WEBHOOK")