File size: 6,215 Bytes
dcf1b21 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | #!/usr/bin/env python3
"""Discover Nova API configuration - simple version without dependencies."""
import json
import os
import sys
import urllib.request
from pathlib import Path
def load_env_file(filepath):
"""Simple .env file loader."""
env_vars = {}
if not filepath.exists():
return env_vars
with open(filepath, 'r') as f:
for line in f:
line = line.strip()
if line and not line.startswith('#') and '=' in line:
key, value = line.split('=', 1)
env_vars[key.strip()] = value.strip()
return env_vars
def request_json(url, access_token):
"""Make a GET request to the Nova API."""
request = urllib.request.Request(url)
request.add_header("Authorization", f"Bearer {access_token}")
request.add_header("Content-Type", "application/json")
try:
with urllib.request.urlopen(request, timeout=10) as response:
body = response.read().decode("utf-8")
return json.loads(body) if body else {}
except urllib.error.HTTPError as exc:
body = exc.read().decode("utf-8") if exc.fp else ""
print(f"Error: Nova API returned status {exc.code}")
print(f"Response: {body}")
return None
except Exception as exc:
print(f"Error: {exc}")
return None
def main():
# Try to load from .env.local first, then .env
env_local = Path("nova-sim/.env.local")
env_file = Path("nova-sim/.env")
env_vars = {}
if env_local.exists():
env_vars = load_env_file(env_local)
print(f"Loaded configuration from {env_local}")
elif env_file.exists():
env_vars = load_env_file(env_file)
print(f"Loaded configuration from {env_file}")
else:
print("Error: No .env or .env.local file found")
print("Create one with at least NOVA_INSTANCE_URL and NOVA_ACCESS_TOKEN")
return 1
# Get configuration
instance_url = env_vars.get("NOVA_INSTANCE_URL") or env_vars.get("NOVA_API")
access_token = env_vars.get("NOVA_ACCESS_TOKEN")
cell_id = env_vars.get("NOVA_CELL_ID", "cell")
if not instance_url:
print("Error: NOVA_INSTANCE_URL (or NOVA_API) not set in .env file")
return 1
if not access_token:
print("Error: NOVA_ACCESS_TOKEN not set in .env file")
return 1
print(f"\nConnecting to Nova instance: {instance_url}")
print(f"Cell ID: {cell_id}")
print()
# Fetch controllers
print("Fetching controllers...")
controllers_url = f"{instance_url}/api/v2/cells/{cell_id}/controllers"
controllers_data = request_json(controllers_url, access_token)
if not controllers_data:
return 1
# Handle both list and dict responses
if isinstance(controllers_data, list):
controllers = controllers_data
else:
controllers = controllers_data.get("instances", [])
if not controllers:
print("No controllers found")
return 1
print(f"Found {len(controllers)} controller(s):")
print()
for controller in controllers:
# Handle both string and dict controller responses
if isinstance(controller, str):
controller_id = controller
else:
controller_id = controller.get("controller", "unknown")
print(f"Controller ID: {controller_id}")
# Fetch motion groups - try cell-level endpoint first
motion_groups_url = f"{instance_url}/api/v2/cells/{cell_id}/motion-groups"
motion_groups_data = request_json(motion_groups_url, access_token)
if not motion_groups_data:
# Try controller-specific endpoint
motion_groups_url = f"{instance_url}/api/v2/cells/{cell_id}/controllers/{controller_id}/motion-groups"
motion_groups_data = request_json(motion_groups_url, access_token)
if not motion_groups_data:
print(" Motion groups: Could not fetch")
continue
motion_groups = motion_groups_data.get("motion_groups", [])
print(f" Motion groups: {len(motion_groups)}")
for mg in motion_groups:
mg_id = mg.get("motion_group", "unknown")
model = mg.get("model_from_controller", "unknown")
name = mg.get("name_from_controller", "")
print(f" - ID: {mg_id}")
print(f" Model: {model}")
if name:
print(f" Name: {name}")
# Fetch motion group description
desc_url = f"{instance_url}/api/v2/cells/{cell_id}/controllers/{controller_id}/motion-groups/{mg_id}/description"
desc_data = request_json(desc_url, access_token)
if desc_data:
tcps = desc_data.get("tcps", {})
if tcps:
print(f" Available TCPs: {', '.join(tcps.keys())}")
print()
# Generate recommended .env configuration
print("\n" + "=" * 60)
print("RECOMMENDED CONFIGURATION")
print("=" * 60)
if controllers:
# Handle both string and dict controller responses
controller = controllers[0]
if isinstance(controller, str):
controller_id = controller
else:
controller_id = controller.get("controller", "unknown")
# Get motion groups for first controller
motion_groups_url = f"{instance_url}/api/v2/cells/{cell_id}/controllers/{controller_id}/motion-groups"
motion_groups_data = request_json(motion_groups_url, access_token)
if motion_groups_data:
motion_groups = motion_groups_data.get("motion_groups", [])
if motion_groups:
mg = motion_groups[0]
mg_id = mg.get("motion_group", "unknown")
model = mg.get("model_from_controller", "unknown")
print("\nAdd/update these in your .env.local file:")
print(f"""
NOVA_INSTANCE_URL={instance_url}
NOVA_ACCESS_TOKEN={access_token}
NOVA_CELL_ID={cell_id}
NOVA_CONTROLLER_ID={controller_id}
NOVA_MOTION_GROUP_ID={mg_id}
NOVA_MOTION_GROUP_MODEL={model}
NOVA_TCP_NAME=Flange
NOVA_RESPONSE_RATE_MS=200
""")
return 0
if __name__ == "__main__":
sys.exit(main())
|