Files
boc/iom/mobile/sdk.py
T
Bernt bae705aa97 ARCHITECTURE: NFC roadmap, edge AI, audit logging
- Add NFC ePassport roadmap (ICAO 9303, eIDAS)
- Add TensorFlow.js edge face detection (BlazeFace)
- Add structured audit logger (GDPR-compliant)
- Risk scoring support

Part of KYC Apple Native UX v1.1.0
2026-06-29 16:24:48 +00:00

261 lines
7.5 KiB
Python

"""
Mobile SDK for quiXzoom app
iOS/Android integration with IOM platform
"""
from typing import Dict, List, Optional
from dataclasses import dataclass
import json
@dataclass
class MobileConfig:
"""Configuration for mobile SDK"""
api_url: str
api_key: str
timeout: int = 30
max_image_size: int = 10 * 1024 * 1024 # 10MB
cache_enabled: bool = True
offline_mode: bool = False
class IOMMobileSDK:
"""
Mobile SDK for quiXzoom app
Features:
- Offline observation capture
- Image compression
- GPS tagging
- Batch sync
- Push notifications
- Visual geolocation (NEW)
- Evidence package extraction (NEW)
"""
def __init__(self, config: MobileConfig):
self.config = config
self.offline_queue: List[Dict] = []
self.cache: Dict = {}
self.visual_geo_enabled = True
def capture_observation(
self,
image_data: bytes,
latitude: float,
longitude: float,
notes: Optional[str] = None
) -> Dict:
"""
Capture observation from mobile device
Args:
image_data: JPEG/PNG image bytes
latitude: GPS latitude
longitude: GPS longitude
notes: Optional notes
Returns:
Observation data
"""
# Compress image
compressed = self._compress_image(image_data)
# Extract visual geolocation evidence (NEW)
evidence_package = None
if self.visual_geo_enabled:
evidence_package = self._extract_evidence(compressed)
# Create observation with evidence
observation = {
"id": f"OBS-MOB-{self._generate_id()}",
"timestamp": self._get_timestamp(),
"latitude": latitude,
"longitude": longitude,
"image_size": len(compressed),
"notes": notes,
"status": "pending",
"evidence_package": evidence_package, # NEW
"visual_geolocation": {
"enabled": self.visual_geo_enabled,
"evidence_layers": len(evidence_package) if evidence_package else 0
}
}
# Queue for sync
if self.config.offline_mode:
self.offline_queue.append(observation)
return {"status": "queued", "observation": observation}
# Sync immediately
return self._sync_observation(observation, compressed)
def sync_offline_queue(self) -> Dict:
"""Sync queued observations"""
results = []
for observation in self.offline_queue:
result = self._sync_observation(observation, None)
results.append(result)
self.offline_queue.clear()
return {
"synced": len(results),
"results": results
}
def get_dashboard(self) -> Dict:
"""Get mobile-optimized dashboard"""
return {
"stats": {
"missions_completed": 12,
"missions_available": 34,
"earnings_usd": 245.50,
"rating": 4.8
},
"nearby_missions": [
{
"id": "MIS-001",
"title": "Street lighting inspection",
"distance_m": 450,
"reward_usd": 15.00,
"deadline": "2026-06-27T18:00:00Z"
},
{
"id": "MIS-002",
"title": "Sidewalk condition survey",
"distance_m": 890,
"reward_usd": 20.00,
"deadline": "2026-06-28T12:00:00Z"
}
],
"notifications": [
{
"type": "mission_available",
"message": "New mission near you!",
"timestamp": "2026-06-26T11:00:00Z"
}
]
}
def submit_mission(
self,
mission_id: str,
observations: List[Dict],
metadata: Optional[Dict] = None
) -> Dict:
"""Submit completed mission"""
submission = {
"mission_id": mission_id,
"submitted_at": self._get_timestamp(),
"observations": observations,
"metadata": metadata or {},
"status": "submitted"
}
# In production, send to API
return {
"status": "submitted",
"submission_id": f"SUB-{self._generate_id()}",
"estimated_review_time": "24h"
}
def get_mission_details(self, mission_id: str) -> Dict:
"""Get mission details"""
return {
"id": mission_id,
"title": "Street lighting inspection",
"description": "Inspect and photograph street lighting in your area",
"requirements": [
"iPhone 12+ or Android 12MP+",
"Daylight photos",
"GPS enabled"
],
"reward_usd": 15.00,
"deadline": "2026-06-27T18:00:00Z",
"location": {
"latitude": 59.3293,
"longitude": 18.0686,
"radius_m": 500
}
}
def _extract_evidence(self, image_data: bytes) -> Dict:
"""Extract evidence package from image (NEW)"""
# In production, call visual geolocation API
# For now, return simulated evidence
return {
"visual_objects": [],
"semantic_objects": [],
"text_detections": [],
"geometric_features": [],
"environmental_signals": [],
"temporal_signals": {}
}
def _compress_image(self, image_data: bytes) -> bytes:
"""Compress image for mobile upload"""
# In production, use PIL to compress
# For now, return as-is
return image_data
def _sync_observation(self, observation: Dict, image_data: Optional[bytes]) -> Dict:
"""Sync observation to server"""
# In production, send to API
return {
"status": "synced",
"observation_id": observation["id"]
}
def _generate_id(self) -> str:
"""Generate unique ID"""
import uuid
return uuid.uuid4().hex[:8]
def _get_timestamp(self) -> str:
"""Get current timestamp"""
from datetime import datetime
return datetime.utcnow().isoformat()
# Example usage
def example_mobile_sdk():
"""Example: Mobile SDK usage"""
print("=== Mobile SDK Demo ===\n")
config = MobileConfig(
api_url="https://api.iom.landvex.com",
api_key="mobile_api_key",
offline_mode=True
)
sdk = IOMMobileSDK(config)
# Capture observation
print("Capturing observation...")
result = sdk.capture_observation(
image_data=b"fake_image_data",
latitude=59.3293,
longitude=18.0686,
notes="Broken street light"
)
print(f"Status: {result['status']}")
# Get dashboard
print("\nGetting dashboard...")
dashboard = sdk.get_dashboard()
print(f"Missions available: {dashboard['stats']['missions_available']}")
print(f"Earnings: ${dashboard['stats']['earnings_usd']}")
# Sync offline queue
print("\nSyncing offline queue...")
sync_result = sdk.sync_offline_queue()
print(f"Synced: {sync_result['synced']} observations")
return sdk
if __name__ == '__main__':
example_mobile_sdk()