Download backend/rules/context.py from subhan07/hvac-agents: direct link, hf CLI and curl.
- Browser
- Download file 4.49 kB
-
https://huggingface.co/subhan07/hvac-agents/resolve/main/backend/rules/context.py
- Command line
-
hf download hf://subhan07/hvac-agents/backend/rules/context.py
-
curl -L -o context.py https://huggingface.co/subhan07/hvac-agents/resolve/main/backend/rules/context.py
4.49 kB
| """Build Rule Engine evaluation context from telemetry + limits.""" | |
| from __future__ import annotations | |
| import os | |
| from datetime import datetime, timedelta, timezone | |
| from typing import Any, Dict, Optional | |
| from backend.agents.runtime.safety import load_limits | |
| from backend.config.engineering_limits import get_limits_config | |
| from backend.services.canonical_telemetry_service import latest_points | |
| from backend.services.hvac_safety_contract import is_safe_mode | |
| def _now() -> datetime: | |
| return datetime.now(timezone.utc).replace(tzinfo=None) | |
| def _latest_normalized(zone_id: str, building_id: Optional[str]) -> Optional[Dict[str, Any]]: | |
| try: | |
| from backend.services.ai_normalized_telemetry import build_ai_records | |
| end = _now() | |
| start = end - timedelta(minutes=30) | |
| payload = build_ai_records( | |
| zone_id=zone_id or "ZONE-01", | |
| t0=start.isoformat(), | |
| t1=end.isoformat(), | |
| step_seconds=60, | |
| building_id=building_id, | |
| ) | |
| for row in reversed(payload.get("records") or []): | |
| q = str(row.get("quality") or "").upper() | |
| if q in ("GOOD", "STALE"): | |
| return row | |
| except Exception: | |
| return None | |
| return None | |
| def _point_lookup(building_id: Optional[str]) -> Dict[str, Dict[str, Any]]: | |
| out: Dict[str, Dict[str, Any]] = {} | |
| try: | |
| for p in latest_points(building_id, limit=500): | |
| pid = str(p.get("point_id") or "") | |
| if pid: | |
| out[pid] = p | |
| except Exception: | |
| pass | |
| return out | |
| def build_rule_context(raw: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: | |
| """Normalize caller payload into a full Rule Engine context.""" | |
| ctx = dict(raw or {}) | |
| building_id = ctx.get("building_id") or os.getenv("HVAC_DEFAULT_BUILDING_ID") or "bldg-corp-hq-01" | |
| zone_id = ctx.get("zone_id") or "ZONE-01" | |
| point_id = ctx.get("point_id") | |
| action = str(ctx.get("action") or "EVALUATE").upper() | |
| points = _point_lookup(building_id) | |
| point_row = points.get(str(point_id or ""), {}) if point_id else {} | |
| old_value = ctx.get("old_value") | |
| if old_value is None and point_row.get("value") is not None: | |
| old_value = point_row.get("value") | |
| new_value = ctx.get("new_value") | |
| if new_value is None: | |
| new_value = ctx.get("target_value") | |
| normalized = ctx.get("normalized") | |
| if normalized is None: | |
| normalized = _latest_normalized(zone_id, building_id) | |
| engineering = get_limits_config() | |
| eng_limits = load_limits(building_id) | |
| telemetry = ctx.get("telemetry") or {} | |
| if not telemetry and point_row: | |
| telemetry = { | |
| "source": point_row.get("source"), | |
| "quality": point_row.get("quality"), | |
| "age_seconds": point_row.get("age_seconds"), | |
| "value": point_row.get("value"), | |
| } | |
| if not telemetry and normalized: | |
| telemetry = { | |
| "source": normalized.get("Source") or normalized.get("source"), | |
| "quality": normalized.get("quality"), | |
| "age_seconds": 0, | |
| } | |
| return { | |
| **ctx, | |
| "action": action, | |
| "building_id": building_id, | |
| "zone_id": zone_id, | |
| "point_id": point_id, | |
| "old_value": old_value, | |
| "new_value": new_value, | |
| "target_value": new_value, | |
| "current_value": old_value if ctx.get("current_value") is None else ctx.get("current_value"), | |
| "opportunity_id": ctx.get("opportunity_id") or ctx.get("opportunity") or ctx.get("id"), | |
| "normalized": normalized, | |
| "points": points, | |
| "point_row": point_row, | |
| "engineering_limits_db": eng_limits, | |
| "engineering_config": engineering, | |
| "telemetry": telemetry, | |
| "safe_mode": is_safe_mode(), | |
| "decision": ctx.get("decision") or "OPTIMIZE", | |
| "supervisory": ctx.get("supervisory") or {"decision": ctx.get("decision") or "OPTIMIZE"}, | |
| "safety": ctx.get("safety") or {"status": "PASS", "passed": True}, | |
| "confidence": ctx.get("confidence") if ctx.get("confidence") is not None else 0.9, | |
| "approval_status": ctx.get("approval_status"), | |
| "user": ctx.get("user") or {}, | |
| "strict": os.getenv("HVAC_RULE_ENGINE_STRICT", "1").strip() not in ("0", "false", "FALSE"), | |
| "skip_audit": bool(ctx.get("skip_audit")), | |
| } | |