| |
| """ |
| Register an edge node with the central SmartClass server. |
| |
| This script registers a new edge device (e.g., Raspberry Pi 5) with the central |
| server, establishing its identity and section assignment. |
| |
| Usage: |
| python scripts/register_edge_node.py --node-id rpi5-room301 --section AIML-3-A --ip 192.168.1.101 |
| """ |
| import argparse |
| import json |
| import socket |
| import sys |
| import urllib.request |
| import urllib.error |
| from datetime import datetime |
|
|
|
|
| def get_system_info() -> dict: |
| """Gather system information for registration.""" |
| import platform |
|
|
| return { |
| "hostname": socket.gethostname(), |
| "platform": platform.platform(), |
| "architecture": platform.machine(), |
| "python_version": platform.python_version(), |
| } |
|
|
|
|
| def register_node( |
| api_url: str, |
| node_id: str, |
| section_key: str, |
| ip_address: str, |
| api_key: str = "", |
| ) -> bool: |
| """Register edge node with central API server.""" |
| system_info = get_system_info() |
|
|
| payload = { |
| "node_id": node_id, |
| "section_key": section_key, |
| "ip_address": ip_address, |
| "hostname": system_info["hostname"], |
| "platform": system_info["platform"], |
| "architecture": system_info["architecture"], |
| "registered_at": datetime.now().isoformat(), |
| } |
|
|
| print(f"📡 Registering edge node: {node_id}") |
| print(f" Section: {section_key}") |
| print(f" IP: {ip_address}") |
| print(f" Hostname: {system_info['hostname']}") |
|
|
| headers = { |
| "Content-Type": "application/json", |
| } |
| if api_key: |
| headers["Authorization"] = f"Bearer {api_key}" |
|
|
| try: |
| data = json.dumps(payload).encode("utf-8") |
| req = urllib.request.Request( |
| f"{api_url}/api/v1/edge-nodes/register", |
| data=data, |
| headers=headers, |
| method="POST", |
| ) |
| with urllib.request.urlopen(req, timeout=15) as resp: |
| result = json.loads(resp.read().decode()) |
| print(f"\n✅ Registration successful!") |
| print(f" Node ID: {result.get('node_id', node_id)}") |
| print(f" Status: {result.get('status', 'registered')}") |
| return True |
|
|
| except urllib.error.HTTPError as e: |
| body = e.read().decode() if e.fp else "" |
| print(f"\n❌ Registration failed: HTTP {e.code}") |
| print(f" Response: {body[:200]}") |
| return False |
|
|
| except urllib.error.URLError as e: |
| print(f"\n❌ Connection failed: {e.reason}") |
| print(f" Is the API server running at {api_url}?") |
| return False |
|
|
|
|
| def main(): |
| parser = argparse.ArgumentParser(description="Register SmartClass edge node") |
| parser.add_argument("--node-id", required=True, help="Unique node identifier") |
| parser.add_argument("--section", required=True, help="Section key (e.g., AIML-3-A)") |
| parser.add_argument("--ip", default="", help="Node IP address (auto-detected if empty)") |
| parser.add_argument("--api-url", default="http://localhost:8000", help="Central API URL") |
| parser.add_argument("--api-key", default="", help="API authentication key") |
|
|
| args = parser.parse_args() |
|
|
| |
| ip_address = args.ip |
| if not ip_address: |
| try: |
| s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
| s.connect(("8.8.8.8", 80)) |
| ip_address = s.getsockname()[0] |
| s.close() |
| except Exception: |
| ip_address = "127.0.0.1" |
|
|
| success = register_node( |
| api_url=args.api_url, |
| node_id=args.node_id, |
| section_key=args.section, |
| ip_address=ip_address, |
| api_key=args.api_key, |
| ) |
|
|
| sys.exit(0 if success else 1) |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|