Salta ai contenuti

Elaborazione e monitoraggio

Dopo che i file di input sono stati caricati, la piattaforma può generare output elaborati (nuvole di punti standardizzate, mesh HLOD, photosphere e così via). Questa guida spiega come elencare le opzioni di elaborazione, avviare l’elaborazione e monitorare i progressi finché ogni output raggiunge uno stato terminale.

Presuppone che tu abbia un bundle con almeno una sessione di caricamento completata e disponga degli scope read:bundle e write:bundle.


L’elaborazione è fire-and-forget: l’API accoda un job di elaborazione e ritorna immediatamente.

sequenceDiagram
  participant Client as Client
  participant RCAPI as RCAPI

  Client->>RCAPI: GET processing/options
  RCAPI-->>Client: options + metadata

  Client->>RCAPI: POST processing
  RCAPI-->>Client: accepted or typed error

  loop until all terminal
    Client->>RCAPI: GET bundle/processings
    RCAPI-->>Client: processing records (status, progress)
  end
MetodoPercorsoScopeScopo
GET/v1/bundles/{bundleId}/processing/optionsread:bundleElencare i possibili tipi di output e i loro metadati
POST/v1/bundles/{bundleId}/processingwrite:bundleAvviare l’elaborazione per gli output richiesti
GET/v1/bundles/{bundleId}/processingsread:bundleElencare i record di elaborazione del bundle per monitorare i progressi
GET/v1/site/{siteId}/bundles/{bundleId}read:hierarchyOttenere il bundle con i suoi componenti di output elaborati (link firmati)

Prima di avviare, scopri quali output il bundle può produrre e quanto costa ciascuno.

GET {api_url}/v1/bundles/{bundleId}/processing/options?page=1&limit=20&sortBy=type&sortDir=ASC
Authorization: Bearer {access_token}
ParametroTipoDescrizione
pagenumberIndice di pagina in base 1 (predefinito 1)
limitnumberDimensione della pagina (predefinito 20, massimo 20)
sortBystringtype o cost (predefinito type)
sortDirstringASC o DESC (predefinito ASC)

La risposta è un elenco paginato ({ items, total }). Ogni opzione descrive un tipo di output:

CampoSignificato
typeTipo di componente di output da passare all’avvio dell’elaborazione (ad esempio StandardizedPointCloud, OgcPointCloudHlod)
hasProcessingtrue quando è già stata avviata un’elaborazione per questo output
costCosto di elaborazione in byte per gli output a pagamento; 0 per gli output del piano gratuito

Esempio:

{
"items": [
{
"type": "StandardizedPointCloud",
"hasProcessing": false,
"cost": 734003200
},
{
"type": "OgcPointCloudHlod",
"hasProcessing": false,
"cost": 734003200
}
],
"total": 2
}

Salta gli output in cui hasProcessing è true a meno che tu non intenda rielaborare.

Passa l’elenco dei tipi di componente di output che vuoi che la pipeline produca, più un campo cost che conferma l’addebito totale dell’elaborazione. Il server somma i valori cost del Passaggio 1 per ogni tipo in requestedComponents e rifiuta la richiesta quando la tua conferma non corrisponde.

L’elaborazione inizia in modo asincrono una volta accettato il costo.

POST {api_url}/v1/bundles/{bundleId}/processing
Authorization: Bearer {access_token}
Content-Type: application/json
{
"requestedComponents": [
"StandardizedPointCloud",
"OgcPointCloudHlod"
],
"cost": 1468006400
}

Nell’esempio precedente, cost è 734003200 + 734003200 dall’elenco delle opzioni del Passaggio 1.

204 No Content: l’elaborazione è stata accettata e accodata.

Quando l’elaborazione non può essere avviata, l’API restituisce 409 Conflict con un error tipizzato:

Valore di errorSignificato
ProcessingCostMismatchIl cost inviato non corrisponde al totale calcolato per gli output richiesti
InsufficientProcessingCapacityIl limite di elaborazione dell’organizzazione verrebbe superato
NoInputDataFoundForProcessingNessun file di input finalizzato è disponibile sul bundle
FailedToLaunchProcessingL’invio alla pipeline non è riuscito per un motivo imprevisto

Esempio:

{
"error": "ProcessingCostMismatch"
}

La validazione strutturale del batch caricato (tipi obbligatori, estensioni, dipendenze) viene applicata dalla pipeline di elaborazione dopo l’avvio. Se la tua sessione di caricamento è stata completata ma ha violato il contratto dei requirements, l’elaborazione potrebbe fallire in seguito anche se ogni file è stato caricato correttamente e la chiamata di avvio ha restituito 204.

Dopo un avvio riuscito, effettua il polling dei record di elaborazione del bundle finché ognuno raggiunge uno stato terminale.

GET {api_url}/v1/bundles/{bundleId}/processings
Authorization: Bearer {access_token}

La risposta è un elenco ({ items, total }) con ogni record di elaborazione del bundle. Non ci sono parametri di query; tutti i record vengono restituiti in un’unica chiamata.

Ogni elemento traccia un job di elaborazione:

CampoSignificato
idIdentificatore del record di elaborazione
statusStato della pipeline (vedi la tabella sotto)
progressPercentuale di completamento (0100) mentre è attivo
createdAtQuando il job è stato creato
updatedAtQuando il job ha cambiato stato l’ultima volta
launchedByIdId dell’utente che ha avviato il job, oppure null
knownErrorsErrori strutturati, ciascuno con un errorCode e i errorFilepaths interessati (null quando non è specifico di un file)
StatoTerminale?Significato
PendingnoIn coda, non ancora avviato
ProcessingnoLa pipeline è in esecuzione
RestartednoIl job è stato riavviato ed è nuovamente in esecuzione
ReadyOutput prodotto con successo
FailedErrore non strutturato della pipeline
FailedToLaunchIl job non è mai entrato nella pipeline
KnownErrorErrore strutturato di validazione o di formato

Effettua il polling finché ogni record non si trova in uno stato terminale (Ready, Failed, FailedToLaunch o KnownError).

Esempio di risposta durante l’esecuzione:

{
"items": [
{
"id": "3f2b1c4d-8e7a-4b2c-9d1e-0a1b3c4d4e6f",
"status": "Processing",
"progress": 42,
"createdAt": "2026-06-01T14:05:00Z",
"updatedAt": "2026-06-01T14:12:00Z",
"launchedById": "b1a2c3d4-5e6f-7a8b-9c0d-1e2f3a2b2c1d",
"knownErrors": []
},
{
"id": "9c0d1e2f-3a4b-5c6d-7e8f-9a0b2c3d3e4f",
"status": "Pending",
"progress": 0,
"createdAt": "2026-06-01T14:05:00Z",
"updatedAt": "2026-06-01T14:05:00Z",
"launchedById": "b1a2c3d4-5e6f-7a8b-9c0d-1e2f3a3b1c1d",
"knownErrors": []
}
],
"total": 2
}

Esempio con un errore noto:

{
"items": [
{
"id": "3f2b1c4d-8e7a-4b2c-9d1e-0a2b3c4d4e5f",
"status": "KnownError",
"progress": 100,
"createdAt": "2026-06-01T14:05:00Z",
"updatedAt": "2026-06-01T14:48:00Z",
"launchedById": "b1a2c3d4-5e6f-7a8b-1c0d-2e6f3a4b5c6d",
"knownErrors": [
{
"errorCode": "MissingTrajectory",
"errorFilepaths": ["scan.las"]
}
]
}
],
"total": 1
}

L’elenco delle elaborazioni non include il type dell’output per record. Per ricollegare gli output completati ai loro tipi di componente e ai link firmati, recupera i componenti del bundle (vedi Recupero degli output elaborati).

  • Intervallo: 1-5 minuti è un valore predefinito ragionevole. L’elaborazione può durare da diversi minuti a diverse ore a seconda della dimensione dell’input.
  • Limiti di frequenza: gli endpoint del bundle condividono un bucket di rate limit con diversi altri endpoint. Evita il polling con frequenza inferiore al minuto.

Una volta che un record di elaborazione raggiunge lo stato Ready, recupera il bundle per ottenere i suoi componenti di output e i relativi link di download firmati. I dettagli del bundle risiedono sull’endpoint della gerarchia:

GET {api_url}/v1/site/{siteId}/bundles/{bundleId}
Authorization: Bearer {access_token}

Questo endpoint richiede lo scope read:hierarchy e restituisce il bundle con il suo array components:

CampoSignificato
idId del bundle
nameNome del bundle
componentsUna voce per ogni componente disponibile (input e output elaborati)

Ogni componente contiene:

CampoSignificato
idId del componente
typeTipo di componente, ad esempio StandardizedPointCloud, OgcPointCloudHlod
versionVersione del componente
signedLinkURL firmato per scaricare il componente; nessun header di autenticazione richiesto
rootsPercorsi del punto di ingresso all’interno del componente, quando applicabile

Esempio:

{
"id": "a6f75b3c-f261-4b27-9a2a-9a6cc4178a13",
"name": "ZF capture 2026-06-01",
"components": [
{
"id": "5d6e7f8a-9b0c-1d2e-3f4a-1b3c7d4e8f0a",
"type": "StandardizedPointCloud",
"version": "1",
"signedLink": "https://cdn…/components/…?X-Amz-…"
}
]
}

Un progetto RealityPlan espone lo stesso bundle tramite GET /v1/reality-plan/{projectId}/bundles/{bundleId} (scope read:twin).

import time
import requests
API_URL = "https://<your-regional-api-url>"
TOKEN = "<access_token>"
BUNDLE_ID = "<bundleId>"
headers = {"Authorization": f"Bearer {TOKEN}"}
base = f"{API_URL}/v1/bundles/{BUNDLE_ID}"
# 1. Scopri gli output.
options = requests.get(
f"{base}/processing/options",
headers=headers,
params={"page": 1, "limit": 20},
).json()
options_by_type = {item["type"]: item for item in options["items"]}
to_process = [
item["type"]
for item in options["items"]
if not item["hasProcessing"]
]
total_cost = sum(options_by_type[t]["cost"] for t in to_process)
print(f"Launching: {to_process} (cost: {total_cost})")
# 2. Avvia l'elaborazione.
response = requests.post(
f"{base}/processing",
headers=headers,
json={"requestedComponents": to_process, "cost": total_cost},
)
if response.status_code == 409:
raise RuntimeError(
f"Processing failed to start: {response.json().get('error')}"
)
response.raise_for_status() # expect 204
# 3. Effettua il polling finché ogni job non è terminale.
TERMINAL = {"Ready", "Failed", "FailedToLaunch", "KnownError"}
POLL_SECONDS = 15
TIMEOUT_SECONDS = 3600
deadline = time.time() + TIMEOUT_SECONDS
while time.time() < deadline:
listing = requests.get(
f"{base}/processings",
headers=headers,
).json()
processings = listing.get("items", [])
for p in processings:
print(f" {p['id']}: {p['status']} ({p['progress']}%)")
if processings and all(p["status"] in TERMINAL for p in processings):
break
time.sleep(POLL_SECONDS)
else:
raise TimeoutError("Processing did not finish within the timeout")

Per recuperare i file di input grezzi che sono stati caricati (per archiviazione, rielaborazione o audit), consulta Scaricare i file di input.