# I WorkShop BR-UTM (Jul/24)

Documentação para participação no WorkShop

# Repositórios e Endpoints

[Apresentação Workshop](https://docs.google.com/presentation/d/17UNKi6QQ_hO4Lv314aAa8VlsqurcgUyg/edit?usp=sharing&ouid=115891639852919271691&rtpof=true&sd=true)

DSS: [https://github.com/dp-icea/dss](https://github.com/dp-icea/dss)

Monitoring: [https://github.com/dp-icea/utm\_monitoring](https://github.com/dp-icea/utm_monitoring)

SCD-Provider Example: [https://github.com/dp-icea/scd\_provider/tree/refactor-golang](https://github.com/dp-icea/scd_provider/tree/refactor-golang)

Swagger: [http://172.18.31.95:9001/](http://172.18.31.95:9001/)

### Endpoints

Validator: [http://montreal.icea.decea.mil.br:64235/verifier/validate](http://montreal.icea.decea.mil.br:64235/verifier/validate)

# Entidades da Simulação

A seguir estão as coordenadas GeoJSON das entidades presentes no cenário de simulação

Visualizador: [http://172.18.35.75:3000/](http://172.18.35.75:3000/)

##### SBR497

<details id="bkmrk-sbr-497-json-%7B-%22type"><summary>GeoJSON</summary>

```json
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "id": 0,
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -48.1622,
              -22.2156
            ],
            [
              -48.1403,
              -22.2004
            ],
            [
              -48.1183,
              -22.1853
            ],
            [
              -48.0963,
              -22.1702
            ],
            [
              -48.0744,
              -22.155
            ],
            [
              -48.0524,
              -22.1399
            ],
            [
              -48.0305,
              -22.1248
            ],
            [
              -48.0086,
              -22.1096
            ],
            [
              -47.9866,
              -22.0945
            ],
            [
              -47.9647,
              -22.0793
            ],
            [
              -47.9428,
              -22.0642
            ],
            [
              -47.9411,
              -22.0504
            ],
            [
              -47.9394,
              -22.0366
            ],
            [
              -47.9378,
              -22.0228
            ],
            [
              -47.9241,
              -22.0294
            ],
            [
              -47.9104,
              -22.0361
            ],
            [
              -47.8967,
              -22.0428
            ],
            [
              -47.9036,
              -22.0588
            ],
            [
              -47.9106,
              -22.0748
            ],
            [
              -47.9176,
              -22.0908
            ],
            [
              -47.9246,
              -22.1068
            ],
            [
              -47.9316,
              -22.1228
            ],
            [
              -47.9385,
              -22.1388
            ],
            [
              -47.9455,
              -22.1548
            ],
            [
              -47.9525,
              -22.1708
            ],
            [
              -47.9549,
              -22.1881
            ],
            [
              -47.9574,
              -22.2054
            ],
            [
              -47.9598,
              -22.2228
            ],
            [
              -47.9623,
              -22.2401
            ],
            [
              -47.9647,
              -22.2574
            ],
            [
              -47.9672,
              -22.2747
            ],
            [
              -47.9696,
              -22.292
            ],
            [
              -47.9721,
              -22.3093
            ],
            [
              -47.9745,
              -22.3266
            ],
            [
              -47.9769,
              -22.3439
            ],
            [
              -47.9955,
              -22.3311
            ],
            [
              -48.014,
              -22.3182
            ],
            [
              -48.0326,
              -22.3054
            ],
            [
              -48.0511,
              -22.2926
            ],
            [
              -48.0696,
              -22.2797
            ],
            [
              -48.0882,
              -22.2669
            ],
            [
              -48.1067,
              -22.2541
            ],
            [
              -48.1252,
              -22.2412
            ],
            [
              -48.1437,
              -22.2284
            ],
            [
              -48.1622,
              -22.2156
            ]
          ]
        ]
      },
      "geometry_name": "geom",
      "properties": {
        "id": "SBR497",
        "feattype": "eac_r"
      }
    }
  ]
}
```

</details><details id="bkmrk-vizualiza%C3%A7%C3%A3o-%C2%A0"><summary>Vizualização</summary>

 [![image.png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-06/scaled-1680-/image.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-06/image.png)

</details>##### OIR USS ICEA

<details id="bkmrk-geojson-%7B%C2%A0-%22type%22%3A-%22"><summary>GeoJSON</summary>

{  
 "type": "FeatureCollection",  
 "features": \[  
 {  
 "type": "Feature",  
 "properties": {},  
 "geometry": {  
 "coordinates": \[  
 \[  
 \[  
 -48.04294926032304,  
 -22.29007270340638  
 \],  
 \[  
 -47.97913316615177,  
 -22.33798336379246  
 \],  
 \[  
 -47.97534728820932,  
 -22.27599508625559  
 \],  
 \[  
 -48.04294926032304,  
 -22.29007270340638  
 \]  
 \]  
 \],  
 "type": "Polygon"  
 }  
 }  
 \]  
}

</details><details id="bkmrk-visualiza%C3%A7%C3%A3o"><summary>Visualização</summary>

[![image.png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-06/scaled-1680-/lROimage.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-06/lROimage.png)

</details>##### Restrição

<details id="bkmrk-geojson-%7B%C2%A0-%22type%22%3A-%22-1"><summary>GeoJSON</summary>

{  
 "type": "FeatureCollection",  
 "features": \[  
 {  
 "type": "Feature",  
 "properties": {},  
 "geometry": {  
 "coordinates": \[  
 \[  
 \[  
 -48.15454075371537,  
 -22.21502857838594  
 \],  
 \[  
 -48.07855594639369,  
 -22.26593911208886  
 \],  
 \[  
 -48.07126578841704,  
 -22.15692404482543  
 \],  
 \[  
 -48.15454075371537,  
 -22.21502857838594  
 \]  
 \]  
 \],  
 "type": "Polygon"  
 }  
 }  
 \]  
}

</details><details id="bkmrk-visualiza%C3%A7%C3%A3o-1"><summary>Visualização</summary>

[![image.png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-06/scaled-1680-/WOpimage.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-06/WOpimage.png)

</details>

# [Desconflito][Autenticação] Roteiro Etapa 1

### Criação de OIR

Uma *Operational Intent Reference(OIR)* é a representação 4D da intenção de operação de uma aeronave não tripulada. No ambiente UTM, a criação e edição de OIRs deve ser coordenada com os outros provedores presentes ou interessados na região da operação. Para possibilitar que essa coordenação seja feita programaticamente, o DECEA manterá um serviço de Descoberta, que é um local onde provedores podem declarar suas operações, assim como obter as operações de outros provedores numa área específica.

Nesse workshop, iremos aprender a interagir com esse serviço de descoberta, chamado DSS. O DSS provido pelo DECEA é derivado da implementação feita pelo projeto [InterUSS](https://interussplatform.org/), que por sua vez é uma implementação dos padrões ASTM-3411 e ASTM-3548. A comunicação com o DSS é feita via HTTP e os contratos estão definidos em: [https://github.com/dp-icea/Protocols](https://github.com/dp-icea/Protocols)

A complexidade na criação da OIR depende de quantas outras entidades (Constraints ou outras OIRs) estão presentes no mesmo volume 4D. Nesse workshop, iniciaremos com o cenário mais simples, evoluindo até o cenário mais complexo.

<details id="bkmrk-oir-isolada-%C2%A0"><summary>OIR isolada</summary>

<div drawio-diagram="456"><img src="https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/drawio/2024-06/drawing-3-1719771300.png" alt=""/></div>

</details><details id="bkmrk-oir-pr%C3%B3xima-a-constr"><summary>OIR próxima a Constraint</summary>

<div drawio-diagram="460"><img src="https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/drawio/2024-06/drawing-3-1719772649.png" alt=""/></div>

</details><details id="bkmrk-oir-com-conflito-mai"><summary>OIR com conflito</summary>

**Maior ou igual prioridade**

<div drawio-diagram="465"><img src="https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/drawio/2024-06/drawing-3-1719773244.png" alt=""/></div>

**Menor prioridade**

<div drawio-diagram="464"><img src="https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/drawio/2024-06/drawing-3-1719773229.png" alt=""/></div>

</details><details id="bkmrk-endpoints-de-coorden"><summary>Endpoints de coordenação</summary>

[![image.png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-06/scaled-1680-/7QUimage.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-06/7QUimage.png)

</details><details id="bkmrk-ativa%C3%A7%C3%A3o-de-oir-%28mom"><summary>Ativação de OIR (Momentos antes do voo)</summary>

Atualizar a OIR no DSS e notificar os Subscribers

[![image.png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-06/scaled-1680-/mIlimage.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-06/mIlimage.png)

</details>#### Autenticação

<details id="bkmrk-autenticar-se-%C2%A0"><summary>Autenticar-se</summary>

A URL base é [`http://montreal.icea.decea.mil.br:64235/token`](http://montreal.icea.decea.mil.br:64235/token)

A requisição deve conter as seguintes *query\_strings*

<table border="1" style="border-collapse: collapse; width: 99.9786%; height: 106.033px;"><colgroup><col style="width: 50.0471%;"></col><col style="width: 50.0471%;"></col></colgroup><tbody><tr style="height: 46.5167px;"><td style="height: 46.5167px;">intended\_audience</td><td style="height: 46.5167px;"><span style="color: rgb(0, 0, 0);">USS de destino da mensagem (Domínio do provedor) Ex. "utm.decea.mil.br"</span></td></tr><tr style="height: 29.8px;"><td style="height: 29.8px;">scope</td><td style="height: 29.8px;"><span style="color: rgb(0, 0, 0);">escopo da requisição. Ex.: utm.strategic\_coordination.</span>

<span style="color: rgb(0, 0, 0);">O scope esperado de cada endpoint está definido no OpenAPI  
</span>

</td></tr><tr style="height: 29.7167px;"><td style="height: 29.7167px;">apikey</td><td style="height: 29.7167px;"><span style="color: rgb(0, 0, 0);">chave recebida do ICEA. Pode-se optar em enviar esse campo no Header da requisição  
</span></td></tr></tbody></table>

</details><details id="bkmrk-validar-autentica%C3%A7%C3%A3o"><summary>Validar autenticação de outro USS</summary>

Ao receber uma requisição de outro USS em seu servidor, é necessário validar o token de autenticação fornecido pelo outro USS. O payload do token contém as seguintes informações:

<table border="1" style="border-collapse: collapse; width: 99.9786%; height: 266.517px;"><colgroup><col style="width: 33.3333%;"></col><col style="width: 33.3333%;"></col><col style="width: 33.3333%;"></col></colgroup><tbody><tr style="height: 46.5167px;"><td style="height: 46.5167px;">aud  
</td><td style="height: 46.5167px;">Domínio do seu provedor.</td><td style="height: 46.5167px;">"utm.provider1.com"  
</td></tr><tr style="height: 63.4px;"><td style="height: 63.4px;">exp  
</td><td style="height: 63.4px;">Timestamp epoch do horário de expiração do token. O token não deve ser aceito a partir desse horário  
</td><td style="height: 63.4px;">1719777868</td></tr><tr style="height: 29.8px;"><td style="height: 29.8px;">iss  
</td><td style="height: 29.8px;">Nome do provedor emissor do token  
</td><td style="height: 29.8px;">ICEA  
</td></tr><tr style="height: 80.2px;"><td style="height: 80.2px;">scope  
</td><td style="height: 80.2px;">Scope autorizado pelo token. Cada endpoint deve aceitar apenas determinados scopes, conforme definido no OpenAPI  
</td><td style="height: 80.2px;">utm.strategic\_coordination  
</td></tr><tr style="height: 46.6px;"><td style="height: 46.6px;">sub  
</td><td style="height: 46.6px;">Nome do provedor origem da requisição. Não deve ser validado</td><td style="height: 46.6px;">"USS1"</td></tr></tbody></table>

Os passos para verificação são

1. Verificar assinatura do token 
    1. Deve-se validar a assinatura do token utilizando a chave pública do ICEA, que será fornecida durante o workshop.
2. Verificar a validade do token 
    1. Deve-se validar que o campo "exp" não seja menor do que o horário atual
3. Verficiar audiência do token 
    1. Deve-se validar que o campo "aud" seja o seu nome, ou seja, o nome do provedor que está recebendo a requisição
4. Verificar o scope 
    1. Deve-se validar que o campo "scope" contenha o scope necessário para requisitar o endpoint. Um token pode possuir mais de um scope separados por espaço em branco.

</details><details id="bkmrk-chave-publica-eco-ut"><summary>Chave Publica Eco-UTM</summary>

\-----BEGIN PUBLIC KEY-----  
MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHkNtpy3GB0YTCl2VCCd22i0rJwI  
GBSazD4QRKvH6rch0IP4igb+02r7t0X//tuj0VbwtJz3cEICP8OGSqrdTSCGj5Y0  
3Oa2gPkx/0c0V8D0eSXS/CUC0qrYHnAGLqko7eW87HW0rh7nnl2bB4Lu+R8fOmQt  
5frCJ5eTkzwK5YczAgMBAAE=  
\-----END PUBLIC KEY-----

</details>

# Introdução Teórica RID e DSS

### Tracking / Network Remote ID

Tracking, Network Remote ID, ou simplesmente Net-RID, é um serviço que permite uma aeronave não tripulada (UAS) prover sua localização, identificação de seu operador e outras informações operacionais relevantes, que podem ser obtidas por entidades autorizadas como órgãos fiscalizadores, outros provedores operando na mesma área, ou até mesmo a população em geral.

Para fornecer o serviço de Net-RID, o provedor deve ser capaz de trocar informações com outros provedores utilizando a interface definida no padrão internacional [ASTM 3411-22a - Standard Specification for Remote ID and Tracking](https://www.astm.org/f3411-22a.html). Para possibilitar a interoperabilidade dos participantes e provedores, deve ser fornecido o serviço de "Service Discovery", que permite a descoberta de outros provedores atuando na mesma área.

<div drawio-diagram="125"><img src="https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/drawio/2023-12/drawing-3-1702641413.png" alt=""/></div>

Diagrama: Modelo conceitual

A ASTM também indica a seguinte documentação de API, como sugestão de interfaces para comunicação entre os serviços acima, que pode ser encontrada no padrão OpenAPI em: [https://github.com/uastech/standards/tree/astm\_rid\_api\_2.1/remoteid](https://github.com/uastech/standards/tree/astm_rid_api_2.1/remoteid)

Para nosso ensaio, seguiremos inicialmente a proposta acima, com possibilidade de alterações conforme o grupo achar necessário.

### Service Discovery

Conforme previsto no padrão ASTM F3411-22a, o service discovery deve possibilitar com que provedores descubram outros provedores atuando na mesma região, para que estes possam se comunicar. No cenário de comunicação HTTP, descobrir um provedor significa conhecer seu endereço web (url) para poder enviar requisições HTTP, em endpoints pré-definidos.

Para isso, a Linux Foundation possui um projeto chamado [InterUSS Platform](https://interussplatform.org/) que possui uma implementação do service discovery de maneira distribuída e sincronizada, denominado DSS (Discovery and Synchronization Service). Distribuído significa que várias entidades podem subir suas próprias instâncias do serviço, descentralizando e garantindo que não exista um ponto único de falha. Sincronizado significa que mesmo que haja múltiplas instâncias, todas possuem as mesmas informações ao mesmo tempo.

No escopo do ensaio, será utilizado o DSS sem nenhuma modificação inicial. Porém, para simplificação dos testes, o serviço possuirá somente uma instância, provida pelo DECEA. Isso permite que os potenciais provedores possam focar em implementar suas responsabilidades específicas e agilizar os processos do ensaio.

### Serviços BR-UTM

Seguindo a matriz de serviços que devem ser atendidos pelo BR-UTM, ao final do ensaio esperamos atender de forma completa o serviço de Discovery Service com o DSS, e o de Tracking and Location Service com o Net-RID. Também esperamos atender de forma parcial o Activity Reporting System com o Display Service do Net-RID.

<div drawio-diagram="127"><img src="https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/drawio/2023-12/drawing-3-1702647159.png" alt=""/></div>

# Autenticação Service Provider

### API Key:

Na comunicação do BR-UTM (imagem abaixo), as requisições devem ser autenticadas e autorizadas. Devido à natureza distribuída da arquitetura, não é viável que cada provedor possua sua lógica de autenticação e autorização.

[![image.png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-04/scaled-1680-/image.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-04/image.png)

Portando, a solução proposta pela ASTM é a de um servidor de autenticação central onde os provedores obtém tokens OAuth2 codificados e assinados em JWT. O Validator da documentação abaixo checa a validade da assinatura do token, utilizando a chave pública do Auth Server.

[![image.png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-04/scaled-1680-/LgFimage.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-04/LgFimage.png)

Um exemplo de troca de mensagens autenticadas é:

[![image.png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-04/scaled-1680-/n2zimage.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-04/n2zimage.png)

### Uso da API Key  


Com sua API Key, você pode realizar ações programaticamente no ECO-UTM:

1. <span style="background-color: rgb(224, 62, 45);">Insira a sua API Key no *header* da requisição;</span>
2. <span style="background-color: rgb(224, 62, 45);">Insira o `scope` </span>
3. <span style="background-color: rgb(224, 62, 45);">Insira o `intended_audience`</span>  
    
    1. <span style="background-color: rgb(224, 62, 45);">Em caso de comunicação com outro USS, o preencha com o conteúdo do campo `manager` da resposta do DSS.</span>

### Validator

[![image.png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-06/scaled-1680-/Pbcimage.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-06/Pbcimage.png)

#### Implementação

Código de exemplo para início da implementação do Auth Server e do Validator em Go

<details id="bkmrk-c%C3%B3digo-exemplo-packa"><summary>Código exemplo</summary>

```go
package main

import (
	"encoding/json"
	"flag"
	"log"
	"net/http"
	"os"
	"strings"

	"github.com/golang-jwt/jwt"
)

var (
	keyFile       = flag.String("private_key_file", "auth.key", "OAuth private key file")
	publicKeyFile = flag.String("public_key_file", "auth.pem", "OAuth public key file")
)

func verifyToken(token string) (bool, error) {
	bytes, err := os.ReadFile(*publicKeyFile)
	if err != nil {
		log.Panic(err)
	}

	publicKey, err := jwt.ParseRSAPublicKeyFromPEM(bytes)
	if err != nil {
		log.Panic(err)
	}

	parts := strings.Split(token, ".")
	err = jwt.SigningMethodRS256.Verify(strings.Join(parts[0:2], "."), parts[2], publicKey)
	if err != nil {
		return false, nil
	}
	return true, nil

}

func main() {

	http.HandleFunc("/validate", func(w http.ResponseWriter, r *http.Request) {
		tokenString := r.URL.Query().Get("token")
		valid, err := verifyToken(tokenString)
		if err != nil {
			log.Panic(err)
		}

		log.Println(valid)
	})

	http.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
		
		token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{
			"aud":   "aud",
			"scope": "scope",
			"iss":   "iss",
			"exp":   "exp",
			"sub":   "sub",
		})

		// Read private key
		bytes, err := os.ReadFile(*keyFile)
		if err != nil {
			log.Panic(err)
		}
		privateKey, err := jwt.ParseRSAPrivateKeyFromPEM(bytes)
		if err != nil {
			log.Panic(err)
		}

		// Sign and get the complete encoded token as a string using the secret
		tokenString, err := token.SignedString(privateKey)
		if err != nil {
			log.Panic(err)
		}

		resp := make(map[string]string)
		resp["access_token"] = tokenString
		jsonResp, err := json.Marshal(resp)
		if err != nil {
			log.Fatalf("Error happened in JSON marshal. Err: %s", err)
		}
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		w.Write(jsonResp)
		return

	})

	log.Fatal(http.ListenAndServe(":9096", nil))
}
```

</details><details id="bkmrk-eco-utm-autenticator"><summary>Eco-UTM Autenticator Public Key</summary>

```
-----BEGIN PUBLIC KEY-----
MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHkNtpy3GB0YTCl2VCCd22i0rJwI
GBSazD4QRKvH6rch0IP4igb+02r7t0X//tuj0VbwtJz3cEICP8OGSqrdTSCGj5Y0
3Oa2gPkx/0c0V8D0eSXS/CUC0qrYHnAGLqko7eW87HW0rh7nnl2bB4Lu+R8fOmQt
5frCJ5eTkzwK5YczAgMBAAE=
-----END PUBLIC KEY-----
```

</details>### Lista de endpoints  


**A lista completa de *endpoints* também está disponível neste [link](http://montreal.icea.decea.mil.br:64235/swagger)<span style="background-color: rgb(224, 62, 45);">, [neste arquivo OpenAPI](https://servicos2.decea.mil.br/br-utm/wiki/attachments/31) e [nesta coleção no Insomina.](https://servicos2.decea.mil.br/br-utm/wiki/attachments/32)</span>**

#### ECO-UTM

A URL base para os seguintes *endpoints* é `<a href="http://montreal.icea.decea.mil.br:64235/">http://montreal.icea.decea.mil.br:64235/</a>`

---

<table border="1" class="align-center" id="bkmrk-get-%2Fuss%2Fflights" style="font-family: var(--font-body); font-size: 14px; width: 100%; height: 29.7969px; border-width: 0px;"><colgroup><col style="width: 75px;"></col><col></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px; border-width: 0px; background-clip: padding-box; color: white; border-radius: 5px; background-color: rgb(97, 175, 254);">**GET**</td><td class="align-left" style="height: 29.7969px; border-width: 0px;">/token</td></tr></tbody></table>

Aprovar token de autenticação do provedor associado ao usuário

<details id="bkmrk-query-parameters-vie"><summary>Path Param</summary>

<table border="1" style="border-collapse: collapse; width: 100%; height: 59.5938px;"><colgroup><col style="width: 50.0642%;"></col><col style="width: 50.0642%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px;">intented\_audience</td><td style="height: 29.7969px;"><span style="color: rgb(0, 0, 0);">user da entetidade de destino da mensagem</span>  
</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">scope</td><td style="height: 29.7969px;"><span style="color: rgb(0, 0, 0);">escopo da requisição</span></td></tr><tr><td>apikey</td><td><span style="color: rgb(0, 0, 0);">chave recebida do ICEA</span></td></tr></tbody></table>

</details><details id="bkmrk-bearer-token-que-tok"><summary>Bearer</summary>

<table border="1" style="border-collapse: collapse; width: 100%; height: 193.969px;"><colgroup><col style="width: 50.0642%;"></col><col style="width: 50.0642%;"></col></colgroup><tbody><tr style="height: 113.781px;"><td style="height: 113.781px;">token</td><td style="height: 113.781px;"><span style="color: rgb(224, 62, 45);"><span style="color: rgb(0, 0, 0);">Bearer token gerado</span></span>  
</td></tr></tbody></table>

</details><details id="bkmrk-response-%7B-%22timestam"><summary>Código exemplo python</summary>

```ht
response = requests.get(
            f"{AUTH_URL}/token",
            params={
                "grant_type": "client_credentials",
                "intended_audience": "localhost",
                "scope": "utm.constraint_management",
                "apikey": "brutm",
            },
        )
```

</details><details id="bkmrk-response-200-success"><summary>Response</summary>

<table border="1" style="border-collapse: collapse; width: 100%; height: 59.5938px;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px;">200  
</td><td style="height: 29.7969px;">Success  
</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">403  
</td><td style="height: 29.7969px;">Non-Authoritative Information</td></tr></tbody></table>

</details><details id="bkmrk-response-body-access"><summary>Response Body</summary>

<table border="1" style="width: 100%;"><tbody><tr><td style="width: 15.145%;">access\_token</td><td style="width: 84.855%;">token de acesso ao ECO-UTM</td></tr></tbody></table>

</details>---

# [Remote ID] Onboarding Service Provider

No contexto do serviço de Network RemoteID, um Service Provider é um provedor USS que é capaz de receber dos seus drones os dados de localização em tempo real, e disponibilizar esses dados on demand em uma API também em tempo real. A especificação a ser seguida está definida pela ASTM F3411-22a. Ainda não foi definido a obrigatoriedade do item 4.4 "*Broadcast Remote ID".* Portanto, nessa página apenas será definido o uso dos itens 4.5 em diante.

### Pré-requisitos técnicos

Para um USS se tornar um provedor de Tracking existem os seguintes pré-requisitos técnicos que não estão no escopo dessa documentação, ficando a critério do provedor como implementar esses pré-requisitos:

1. Possuir um servidor HTTP para solicitar e receber as requisições listadas abaixo
2. Possuir infraestrutura para obter os dados de posição instantânea do drone. Esses dados devem estar disponíveis em tempo real no servidor HTTP

### Fluxograma

<div drawio-diagram="173"><img src="https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/drawio/2024-01/drawing-3-1704906440.png" alt=""/></div>

### Endpoints

A dinâmica de comunicação entre Service Provider, Display Provider e DSS está descrita na norma ASTM 3411-22a. Para facilitar o entendimento, alguns possíveis cenários de utilização estão descritos na página [Cenários](https://servicos2.decea.mil.br/br-utm/wiki/books/documentacao-tecnica/page/cenarios "Cenários").

O padrão seguido no ensaio será o descrito em [https://github.com/dp-icea/Protocols/tree/main/remoteid](https://github.com/dp-icea/Protocols/tree/main/remoteid)

Conforme o padrão OpenAPI acima, os endpoints que o Service Provider precisará prover

---

<table border="1" class="align-center" id="bkmrk-get-%2Fuss%2Fflights" style="font-family: var(--font-body); font-size: 14px; width: 100%; height: 29.8px; border-width: 0px;"><colgroup><col style="width: 75px;"></col><col></col></colgroup><tbody><tr style="height: 29.8px;"><td style="height: 29.8px; border-width: 0px; background-clip: padding-box; color: white; border-radius: 5px; background-color: rgb(97, 175, 254);">**GET**</td><td class="align-left" style="height: 29.8px; border-width: 0px;">/uss/flights</td></tr></tbody></table>

Endpoint onde os Display Providers obterão os dados de tracking das aeronaves sob responsabilidade do Service Provider em uma determinada área

<details id="bkmrk-query-parameters-vie"><summary>Query Parameters</summary>

<table border="1" style="border-collapse: collapse; width: 100%; height: 193.969px;"><colgroup><col style="width: 33.3333%;"></col><col style="width: 33.3333%;"></col><col style="width: 33.3333%;"></col></colgroup><tbody><tr style="height: 113.781px;"><td style="height: 113.781px;">view</td><td style="height: 113.781px;">Área da solicitação, representada por dois pontos no formato `lat1,lng1,lat2,lng2`. Os pontos são as extremidades da diagonal de um quadrado, onde esse quadrado representa a área da solicitação</td><td style="height: 113.781px;">29.978,31.132,29.980,31.135</td></tr><tr style="height: 80.1875px;"><td style="height: 80.1875px;">recent\_positions\_duration</td><td style="height: 80.1875px;">Se for maior que zero, indica que a requisição deve enviar todas as posições do drone nos últimos N segundos. Valor máximo: 60.

Se for zero, indica que deve ser enviado apenas a última posição do drone

</td><td style="height: 80.1875px;">60</td></tr></tbody></table>

</details><details id="bkmrk-response-%7B-%22timestam"><summary>Response</summary>

```json
{
  "timestamp": {
    "value": "1985-04-12T23:20:50.52Z",
    "format": "RFC3339"
  },
  "flights": [
    {
      "id": "PR-333334433.0dfe0e82-fd7a-44d9-af17-7fdd42751b45",
      "aircraft_type": "Helicopter",
      "current_state": RIDAircraftState,
      "operating_area": OperatingArea,
      "simulated": false,
      "recent_positions" = [ RIDRecentAircraftPosition ]
    }
  ],
  "no_isas_present": false
}
```

<table border="1" style="border-collapse: collapse; width: 100%; height: 438.109px;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px;">timestamp</td><td style="height: 29.7969px;">Horário em que o Service Provider recebeu a requisição</td></tr><tr style="height: 124.953px;"><td style="height: 124.953px;">flights.id</td><td style="height: 124.953px;">ID único do provedor que identifica um voo em particular. Deverá vir no formato: "UAS\_ID.FLIGHT\_ID", onde UAS\_ID é código SISANT da aeronave, e FLIGHT\_ID é o uuid da solicitação do voo realizada no ECO-UTM.

</td></tr><tr style="height: 63.3906px;"><td style="height: 63.3906px;">flights.aircraft\_type</td><td style="height: 63.3906px;">Tipo de aeronave no padrão ICAO. Para drones, o tipo = Helicopter. Para drones de asa fixa que conseguem decolar verticalmente, o tipo = "HybridLift"</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">flights.current\_state</td><td style="height: 29.7969px;">Dados do tracking de fato da aeronave, no momento atual.</td></tr><tr style="height: 63.3906px;"><td style="height: 63.3906px;">flights.operating\_area</td><td style="height: 63.3906px;">A área que a aeronave se encontra. Deve ser usado apenas quando o campo "flights.current\_state" não está preenchido.</td></tr><tr style="height: 63.3906px;"><td style="height: 63.3906px;">flights.recent\_positions</td><td style="height: 63.3906px;">Lista de posições recentes da aeronave. Deve ser informado apenas quando as "recent\_positions" foram requisitadas.</td></tr><tr style="height: 63.3906px;"><td style="height: 63.3906px;">no\_isas\_present</td><td style="height: 63.3906px;">Indica se o provedor não possui nenhuma ISA na região informada. Caso esse valor retorne verdadeiro, o requisitante deve parar de realizar requisições para a área.</td></tr></tbody></table>

</details>---

<table border="1" class="align-center" id="bkmrk-get-%2Fuss%2Fflights%2F%7Bid" style="font-family: var(--font-body); font-size: 14px; width: 100%; height: 29.7969px; border-width: 0px;"><colgroup><col style="width: 9.25926%;"></col><col style="width: 90.7407%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px; border-width: 0px; background-clip: padding-box; color: white; border-radius: 5px; background-color: #61affe;">**GET**</td><td class="align-left" style="height: 29.7969px; border-width: 0px;">/uss/flights/{id}/details</td></tr></tbody></table>

Endpoint onde os Display Providers obterão dados específicos de um determinado voo

<details id="bkmrk-path-parameters-id-i"><summary>Path Parameters</summary>

<table border="1" style="border-collapse: collapse; width: 100%; height: 29.7969px;"><colgroup><col style="width: 50.0642%;"></col><col style="width: 25.0321%;"></col><col style="width: 25.0321%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px;">id</td><td style="height: 29.7969px;">ID único do provedor para identificar o voo</td><td>b41f2785-1182-4c2e-82d5-f72f754b3fe2.0dfe0e82-fd7a-44d9-af17-7fdd42751b45</td></tr></tbody></table>

</details><details id="bkmrk-response-%7B-%22details%22"><summary>Response</summary>

```json
{
  "details": {
    "id": "b41f2785-1182-4c2e-82d5-f72f754b3fe2.0dfe0e82-fd7a-44d9-af17-7fdd42751b45",
    },
    "uas_id": {
      "registration_id": "PR-333334433",
    },
    "operator_id": "HUKMBB",
    "operator_location": {
      "position": {
        "lng": -118.456,
        "lat": 34.123
      },
      "altitude": {
        "value": 19.5,
        "reference": "W84",
        "units": "M"
      },
      "altitude_type": "Takeoff"
    },
    "operation_description": "Descrição do voo, mesma descrição informada no SARPAS"
  }
}
```

<table border="1" style="border-collapse: collapse; width: 100%; height: 178.781px;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px;">uas\_id</td><td style="height: 29.7969px;">Código SISANT da aeronave</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">operator\_id</td><td style="height: 29.7969px;">Código SARPAS do operador</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">operator\_location</td><td style="height: 29.7969px;">Localização do operador. Opcional</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">operation\_description</td><td style="height: 29.7969px;">Descrição da Operação conforme solicitação no SARPAS</td></tr></tbody></table>

</details>---

<table border="1" class="align-center" id="bkmrk-get-%2Fuss%2Fidentificat" style="font-family: var(--font-body); font-size: 14px; width: 100%; height: 29.7969px; border-width: 0px;"><colgroup><col style="width: 9.25926%;"></col><col style="width: 90.7407%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px; border-width: 0px; background-clip: padding-box; color: white; border-radius: 5px; background-color: #61affe;">**GET**</td><td class="align-left" style="height: 29.7969px; border-width: 0px;">/uss/identification\_service\_areas/{id}</td></tr></tbody></table>

Endpoint para obter o volume 4D de uma ISA controlada pelo Service Provider

<details id="bkmrk-path-parameters-id-u"><summary>Path Parameters</summary>

<table border="1" style="border-collapse: collapse; width: 100%; height: 29.7969px;"><colgroup><col style="width: 50.0642%;"></col><col style="width: 25.0321%;"></col><col style="width: 25.0321%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px;">id</td><td style="height: 29.7969px;">UUID da área possuída pelo provedor</td><td>UUID</td></tr></tbody></table>

</details><details id="bkmrk-response-%7B-%22extents%22"><summary>Response</summary>

```json
{
  "extents": {
    "volume": {
      "outline_circle": {
        "center": {
          "lng": -118.456,
          "lat": 34.123
        },
        "radius": {
          "value": 300.183,
          "units": "M"
        }
      },
      "outline_polygon": {
        "vertices": [
          {
            "lng": -118.456,
            "lat": 34.123
          },
          {
            "lng": -118.456,
            "lat": 34.123
          },
          {
            "lng": -118.456,
            "lat": 34.123
          }
        ]
      },
      "altitude_lower": {
        "value": 19.5,
        "reference": "W84",
        "units": "M"
      },
      "altitude_upper": {
        "value": 19.5,
        "reference": "W84",
        "units": "M"
      }
    },
    "time_start": {
      "value": "1985-04-12T23:20:50.52Z",
      "format": "RFC3339"
    },
    "time_end": {
      "value": "1985-04-12T23:20:50.52Z",
      "format": "RFC3339"
    }
  }
}
```

<table border="1" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr><td>volume</td><td>Volume 4D da área específica</td></tr></tbody></table>

</details>### Interação com DSS

O Service Provider, conforme definido no padrão ASTM3411-22a, deve criar entidades de área 4D denominadas Identification Service Area (ISA), onde este proverá o serviço de tracking. Os endpoints expostos pelo DSS estão descritos no arquivo OpenAPI descrito acima.

---

Como exemplo, o endpoint abaixo é onde o Service Provider realizará a criação da ISA no DSS:

<table border="1" class="align-center" id="bkmrk-put-%2Fdss%2Fidentificat" style="font-family: var(--font-body); font-size: 14px; width: 100%; height: 29.7969px; border-width: 0px;"><colgroup><col style="width: 9.25926%;"></col><col style="width: 90.7407%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px; border-width: 0px; background-clip: padding-box; color: white; border-radius: 5px; background-color: #fca130;">**PUT**</td><td class="align-left" style="height: 29.7969px; border-width: 0px;">/dss/identification\_service\_area/{id}</td></tr></tbody></table>

Endpoint exposto pelo DSS onde o Service Provider realizará a criação da ISA. Essa área deve ser idêntica à area solicitada e aprovada no Sarpas

<details id="bkmrk-path-param-id-uuid-g"><summary>Path Param</summary>

<table border="1" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr><td>id</td><td>UUID da ISA. Deve ser o mesmo UUID devolvido pelo ECO-UTM após a criação da solicitação de voo.  
</td></tr></tbody></table>

</details><details id="bkmrk-body-%7B-%22extents%22%3A-%7B-"><summary>Body</summary>

```json
{
  "extents": {
    "volume": {
      "outline_circle": {
        "center": {
          "lng": -118.456,
          "lat": 34.123
        },
        "radius": {
          "value": 300.183,
          "units": "M"
        }
      },
      "outline_polygon": {
        "vertices": [
          {
            "lng": -118.456,
            "lat": 34.123
          },
          {
            "lng": -118.456,
            "lat": 34.123
          },
          {
            "lng": -118.456,
            "lat": 34.123
          }
        ]
      },
      "altitude_lower": {
        "value": 19.5,
        "reference": "W84",
        "units": "M"
      },
      "altitude_upper": {
        "value": 19.5,
        "reference": "W84",
        "units": "M"
      }
    },
    "time_start": {
      "value": "1985-04-12T23:20:50.52Z",
      "format": "RFC3339"
    },
    "time_end": {
      "value": "1985-04-12T23:20:50.52Z",
      "format": "RFC3339"
    }
  },
  "uss_base_url": "https://example.com/rid"
}
```

Campos notáveis

<table border="1" style="border-collapse: collapse; width: 100%; height: 76.3907px;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr style="height: 46.5938px;"><td style="height: 46.5938px;">volume</td><td style="height: 46.5938px;">Polígono **OU** círculo da área, idêntico ao definido no SARPAS</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">altitude\_lower, altitude\_upper</td><td style="height: 29.7969px;">Altitude geodésica (WSG84, W84) máxima e mínima em metros.

</td></tr><tr><td>time\_start, time\_end</td><td>Horário de início e fim da área. Todos os horários devem estar no timezone Zulo (UTC+0). O único formato suportado é "RFC3339"

</td></tr><tr><td>uss\_base\_url</td><td>URL a qual o Service Provider irá responder à solicitações. Não deve conter uma barra '/' ao final. Sugere-se utilizar uma URL e não um IP.

</td></tr></tbody></table>

</details><details id="bkmrk-response-%7B-%22subscrib"><summary>Response</summary>

```json
{
  "subscribers": [],
  "service_area": {
    "uss_base_url": "https://example.com/rid",
    "owner": "myuss",
    "time_start": {
      "value": "1985-04-12T23:20:50.52Z",
      "format": "RFC3339"
    },
    "time_end": {
      "value": "1985-04-12T23:20:50.52Z",
      "format": "RFC3339"
    },
    "version": "string",
    "id": "string"
  }
}
```

Campos notáveis

<table border="1" style="border-collapse: collapse; width: 100%; height: 141.781px;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr style="height: 63.3906px;"><td style="height: 63.3906px;">subcribers</td><td style="height: 63.3906px;">Lista dos atuais subcribers dessa área. Caso a lista não esteja vazia, é **OBRIGATÓRIO** o envio da ISA para cada um dos subscribers listados</td></tr><tr style="height: 78.3906px;"><td style="height: 78.3906px;">version</td><td style="height: 78.3906px;">Versão da ISA, gerado pelo DSS, para garantia de integridade. É necessário utilizar esse campo para atualizar ou deletar uma ISA.</td></tr></tbody></table>

</details>

# [Tracking] Onboarding Display Provider

No contexto do serviço de Tracking, um Display Provider é um provedor USS que tem objetivo de exibir a posição de drones em tempo real para seus usuários.

### Pré-requisitos técnicos

Para um USS se tornar um provedor de display de Tracking existem os seguintes pré-requisitos técnicos que não estão no escopo dessa documentação, ficando a critério do provedor como implementar esses pré-requisitos:

1. Possuir um servidor HTTP para solicitar e receber requisições
2. Possuir App para visualização de posição de drones

### Autenticação

Para o ensaio, a autenticação será feita em um serviço OAuth centralizado do DECEA, ainda a ser descrito.

### Endpoints

A dinâmica de comunicação entre Service Provider, Display Provider e DSS está descrita na norma ASTM 3411-22a. Para facilitar o entendimento, alguns possíveis cenários de utilização estão descritos na página [Cenários](https://servicos2.decea.mil.br/br-utm/wiki/books/documentacao-tecnica/page/cenarios "Cenários").

O padrão seguido no ensaio será o descrito em [https://github.com/uastech/standards/tree/astm\_rid\_api\_2.1/remoteid](https://github.com/uastech/standards/tree/astm_rid_api_2.1/remoteid)

Conforme o padrão OpenAPI acima, os endpoints que o Display Provider precisará prover:

<table border="1" class="align-center" id="bkmrk-get-%2Fuss%2Fflights" style="font-family: var(--font-body); font-size: 14px; width: 100%; height: 29.8px; border-width: 0px;"><colgroup><col style="width: 75px;"></col><col></col></colgroup><tbody><tr style="height: 29.8px;"><td style="height: 29.8px; border-width: 0px; background-clip: padding-box; color: white; border-radius: 5px; background-color: rgb(73, 204, 144);">**POST**</td><td class="align-left" style="height: 29.8px; border-width: 0px;">/uss/identification\_service\_areas/{id}</td></tr></tbody></table>

<details id="bkmrk-path-parameters-id-u-1"><summary>Path Parameters</summary>

<table border="1" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr><td>id</td><td>UUID da ISA</td></tr></tbody></table>

</details><details id="bkmrk-request-body-%7B-%22serv"><summary>Request Body</summary>

</details>### Interação com DSS

O Service Provider, conforme definido no padrão ASTM3411-22a, deve criar entidades de Subscription em uma área específica, para encontrar os atuais Service Providers, e também para receberem notificações caso novos provedores se registrem na área. Os endpoints expostos pelo DSS estão descritos no arquivo OpenAPI descrito acima.

Como exemplo, o endpoint abaixo é para criação de Subscriptions:

<table border="1" class="align-center" id="bkmrk-put-%2Fdss%2Fidentificat" style="font-family: var(--font-body); font-size: 14px; width: 100%; height: 29.7969px; border-width: 0px;"><colgroup><col style="width: 9.25926%;"></col><col style="width: 90.7407%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px; border-width: 0px; background-clip: padding-box; color: white; border-radius: 5px; background-color: #fca130;">**PUT**</td><td class="align-left" style="height: 29.7969px; border-width: 0px;">/dss/subscriptions/{id}</td></tr></tbody></table>

<details id="bkmrk-path-parameters-id-u"><summary>Path Parameters</summary>

<table border="1" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr><td>id</td><td>UUID da Subscription, criado pelo Display Provider</td></tr></tbody></table>

</details><details id="bkmrk-request-body-%7B-%22exte"><summary>Request Body</summary>

```json
{
  "extents": {
    "volume": {
      "outline_circle": {
        "center": {
          "lng": -118.456,
          "lat": 34.123
        },
        "radius": {
          "value": 300.183,
          "units": "M"
        }
      },
      "outline_polygon": {
        "vertices": [
          {
            "lng": -118.456,
            "lat": 34.123
          },
          {
            "lng": -118.456,
            "lat": 34.123
          },
          {
            "lng": -118.456,
            "lat": 34.123
          }
        ]
      },
      "altitude_lower": {
        "value": 19.5,
        "reference": "W84",
        "units": "M"
      },
      "altitude_upper": {
        "value": 19.5,
        "reference": "W84",
        "units": "M"
      }
    },
    "time_start": {
      "value": "1985-04-12T23:20:50.52Z",
      "format": "RFC3339"
    },
    "time_end": {
      "value": "1985-04-12T23:20:50.52Z",
      "format": "RFC3339"
    }
  },
  "uss_base_url": "https://example.com/rid"
}
```

Campos notáveis

<table border="1" style="border-collapse: collapse; width: 100%; height: 76.3907px;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr style="height: 46.5938px;"><td style="height: 46.5938px;">volume</td><td style="height: 46.5938px;">Polígono **OU** círculo da área, idêntico ao definido no SARPAS</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">altitude\_lower, altitude\_upper</td><td style="height: 29.7969px;">Altitude geodésica (WSG84, W84) máxima e mínima em metros.

</td></tr><tr><td>time\_start, time\_end</td><td>Horário de início e fim da área. Todos os horários devem estar no timezone Zulo (UTC+0). O único formato suportado é "RFC3339"

</td></tr><tr><td>uss\_base\_url</td><td>URL a qual o Service Provider irá responder à solicitações. Não deve conter uma barra '/' ao final. Sugere-se utilizar uma URL e não um IP.

</td></tr></tbody></table>

</details><details id="bkmrk-response-body-%7B-%22ser"><summary>Response Body</summary>

```json
{
  "service_areas": [],
  "subscription": {
    "id": "string",
    "uss_base_url": "https://example.com/rid",
    "owner": "myuss",
    "notification_index": 0,
    "time_end": {
      "value": "1985-04-12T23:20:50.52Z",
      "format": "RFC3339"
    },
    "time_start": {
      "value": "1985-04-12T23:20:50.52Z",
      "format": "RFC3339"
    },
    "version": "string"
  }
}
```

<table border="1" style="border-collapse: collapse; width: 100%; height: 122.984px;"><colgroup><col style="width: 50%;"></col><col style="width: 50%;"></col></colgroup><tbody><tr style="height: 63.3906px;"><td style="height: 63.3906px;">service\_areas</td><td style="height: 63.3906px;">Lista de ISAs já existentes no volume 4D. Caso a lista não esteja vazia, o Display Provider deve solicitar os dados de telemetria para as URLs definidas na lista</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">version</td><td style="height: 29.7969px;">Versão da Subscription, gerado pelo DSS, para garantia de integridade. É necessário utilizar esse campo para atualizar ou deletar uma Subscription.</td></tr></tbody></table>

</details>

# [USS Qualifier] Teste automatizado de Provedor

US: [https://pista.decea.mil.br/project/br-utm-tecnologia/us/41?milestone=309](https://pista.decea.mil.br/project/br-utm-tecnologia/us/41?milestone=309)

#### Introdução

A [InterUSS](https://interussplatform.org/) disponibiliza um conjunto de testes suites automatizados ([USS QUALIFIER](https://github.com/interuss/monitoring)) para validar os conformidade na implementação de UAS Service Suppliers (USS).

Validação dos seguintes critérios de conforme:  
\- [Remote ID ](https://www.astm.org/f3411-22a.html)(ASTM F3411-19/22);  
-[ Strategic Conflict Detection ](https://www.astm.org/f3548-21.html)(ASTM F3548-21);  
\- UAS Traffic Management (UTM) UAS Service Supplier (USS) Interoperability Specification.

Como a implementação do DSS feita pelo time de pesquisa do ICEA foi feita a partir da solução da InterUSS, para um provedor se integrar ao nosso ecossistema, sua implementação deve estar em concordância com as normas utilizadas em sua implementação.

O objetivo dessa US é implementar a configuração de um ambiente de testes automatizada a partir de um arquivo .env

#### Solução

Para utilizar USS locais em seus testes, deve-se subir um container contendo a aplicação e sua configuração de ambiente, a qual deve conter as seguintes variáveis:

```yaml
 environment:
      - MOCK_USS_AUTH_SPEC=DummyOAuth(http://oauth.authority.localutm:8085/token,uss1)
      - MOCK_USS_DSS_URL=http://dss.uss1.localutm
      - MOCK_USS_PUBLIC_KEY=/var/test-certs/auth2.pem
      - MOCK_USS_TOKEN_AUDIENCE=scdsc.uss1.localutm,localhost,host.docker.internal
      - MOCK_USS_BASE_URL=http://scdsc.uss1.localutm
      - MOCK_USS_SERVICES=scdsc,versioning,interaction_logging,flight_planning
      - MOCK_USS_INTERACTIONS_LOG_DIR=output/scdsc_a_interaction_logs
      - MOCK_USS_PORT=80
      - MOCK_USS_PROXY_VALUES=x_for=1,x_proto=1,x_host=1,x_prefix=1,x_port=1
```

Após configurar e implantar o USS, pode-se configurar o test suite que deseja executar. Como existem perfis diferentes de USS, foram disponibilizados arquivos de configuração visando validar conformes mais específicos dos seus respectivos tipos, estes podem ser encontrados no diretório `monitoring/monitoring/uss_qualifier/configurations/dev/`

[![image.png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/scaled-1680-/Efcimage.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/Efcimage.png)

Caso seja necessário criar um novo arquivo de teste, é necessário implementá-lo através de um arquivo .yaml ou JSON seguindo as guidelines definidas nesse [README](https://github.com/interuss/monitoring/tree/03a462d7a209528b885ffa9651d936e8b4df8f18/monitoring/uss_qualifier/configurations)

#### How to

[Quick start guide](https://github.com/interuss/monitoring/tree/main/monitoring/uss_qualifier)

```bash

git clone https://github.com/interuss/monitoring.git

cd monitoring

#deploys local infrastructure containing DSS, database and Auth Server 
make start-locally

COMPOSE_PROFILES='' make start-uss-mocks

cd /monitoring/uss_qualifier

./run_locally.sh

```

# OIR Status

<span style="color: rgb(34, 34, 34); font-family: var(--font-heading, var(--font-body)); font-size: 1.666em; font-weight: 400;">Responsabilidades Provedores</span>

- <span style="text-decoration: underline;">Utilizar todos os estados das OIRs</span>
    - Ao criar uma OIR, ela está no estado "Accepted". Quando a operação iniciar, o provedor deve mudar o status para "Activated". Ao fim da operação, o provedor deve encerrar a OIR, deletando ela do DSS.
    - Em casos de Não conformidade e contingência, o provedor deve mudar o status da OIR. Os outros provedores subscritos na área devem agir de acordo com a nova situação.
    - [![image.png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/scaled-1680-/qRoimage.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/qRoimage.png)
- <span style="text-decoration: underline;">Utilizar NTP do ICEA</span>
    - O ICEA disponibilizará um servidor NTP para sincronizar os horários entre todos os provedores.
    - [![image.png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/scaled-1680-/dqbimage.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/dqbimage.png)
- <span style="text-decoration: underline;">Utilizar altitude WSG84</span>
    - Padronizar o uso de altitude utilizando o padrão WSG84.
- <span style="text-decoration: underline;">Utilizar autenticação</span>
    - Para comunicação com o DSS e entre provedores, toda requisição deve possuir um token emitido pelo servidor de autenticação do ICEA
- <span style="text-decoration: underline;">Utilizar campo de prioridade na OIR</span>
    - Os provedores devem considerar o campo "priority" na criação de OIR.
    - Uma OIR com prioridade maior pode "sobrescrever" uma com prioridade menor. Ou seja, as OIRs com maior prioridade podem ser criadas onde já existia uma outra OIR com prioridade menor.
    - A tabela descrevendo qual a prioridade de cada tipo de operação ainda será definida.
- <span style="text-decoration: underline;">Permitir conflito entre voos VLOS/EVLOS</span>
    - OIRs para voos visuais podem ter conflito com outras OIRs de voos visuais.
    - OIRs para voos não visuais não podem ter conflito com nenhuma outra OIR, de nenhum tipo

# Modelagem de Processos - Autorização de Voo por Provedores

O processo habitual de autorização de voo por provedores deve seguir o seguinte fluxo:

[![0 - Fluxo.png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/scaled-1680-/0-fluxo-1.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/0-fluxo-1.png "Teste")

Fluxo de Autorização e Ativação de Voo

---

#### Autorização de Voo

O processo de Autorização de Voo (P1) é a primeira etapa do desconflito estratégico de uma operação com drone. O processo começa com um pedido do operador. Esse pedido deve seguir um padrão (ainda não definido), e esse padrão deve ser validado pelo provedor USS. Após, o provedor deve realizar a checagem de desconflito estratégico, e por fim cadastrar o novo voo no ECO-UTM. Caso alguma checagem falhe, o provedor deve notificar o operador dessa falha. É permitido, porém não obrigatório, que o USS sugira alternativas para o operador em casos de rejeição.

[![1 - Autorização de Voo (1).png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/scaled-1680-/1-autorizacao-de-voo-1.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/1-autorizacao-de-voo-1.png)

P1 - Autorização de Voo

[![1.1 - Desconflito Estratégico (1).png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/scaled-1680-/1-1-desconflito-estrategico-1.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/1-1-desconflito-estrategico-1.png)

P1.1 - Desconflito Estratégico

---

#### Ativação de Voo

Após ter seu voo aprovado, o operador deve solicitar a ativação do voo instantes antes de sua execução. Nessa etapa, o provedor deve garantir que a autorização de voo continua válida, e que as condições de voo (condições ainda não definidas) permitem a realização segura do voo. Após a checagem, o USS notifica o operador que ele pode inicar a operação.

Então, o provedor aguarda notificação do operador sobre o encerramento da operação. Recebendo a notificação, o operador deve encerrar o plano de voo no ECO-UTM.

[![2 - Ativação de voo (3).png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/scaled-1680-/2-ativacao-de-voo-3.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/2-ativacao-de-voo-3.png)

P2 - Ativação de Voo

---

#### Mudanças Dinâmicas

No período entre a autorização e a ativação, pode ocorrer mudanças nas condições do espaço aéreo, como uma nova restrição ou um novo voo com maior prioridade. Nesses casos, é de suma importância que o USS notifique o operador dessa atualização, para evitar frustrações do operador na hora da ativação do voo.

[![3 - Mudanças Dinâmicas (1).png](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/scaled-1680-/3-mudancas-dinamicas-1.png)](https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/gallery/2024-05/3-mudancas-dinamicas-1.png)

P3 - Mudanças Dinâmicas

---

#### Emergência

WIP

# Operações USS: Diagramas de Sequencia

#### Cenário 1:

Apenas um Service provider e nenhum Display provider na área durante o Voo

<div drawio-diagram="255"><img src="https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/drawio/2024-02/drawing-3-1709118152.png" alt=""/></div>

#### Cenário 2:

Service provider cria área onde já existe uma Subscription (Display Provider)

<div drawio-diagram="730"><img src="https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/drawio/2025-07/drawing-3-1752236349.png" alt=""/></div>

#### Cenário 3:

Criação de Subscription onde já exista ISA

<div drawio-diagram="116"><img src="https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/drawio/2023-12/drawing-3-1702578754.png" alt=""/></div>

#### Cenário 4:

Usuário do Display Provider deseja visualizar uma área. Nessa área já existe um Service Provider (USS 1), e durante a exibição, um novo Service Provider (USS 2) inicia operações na área. Esse cenário foi adaptado da documentação do InterUSS DSS.

<div drawio-diagram="128"><img src="https://servicos2.decea.mil.br/br-utm/wiki/uploads/images/drawio/2023-12/drawing-3-1702692143.png" alt=""/></div>

# [USS][Desconflito] Código Exemplo

Exemplo de código Provedor de Desconflito (Go e Python): [https://github.com/dp-icea/scd\_provider](https://github.com/dp-icea/scd_provider)

Para realizar autenticação:

1. Verificar se está gerando o token

Para criar OIR:

1. Enviar GeoJSON da área desejada

Abaixo segue exemlpo de código em Python:

<details id="bkmrk-app.py-from-flask-im"><summary>app.py</summary>

```python
from flask import Flask, request

from dss import Dss

import json

app = Flask(__name__)

database = {}

dss = Dss()


@app.route('/uss/v1/operational_intents/<operational_intent_id>', methods=['GET'])
def get_oir(operational_intent_id):
    print(database)
    if operational_intent_id not in database:
        return {"msg": 'No such OIR'}, 404

    return json.dumps(database[operational_intent_id], default=lambda o: o.__dict__)


@app.route('/injection/oir', methods=['PUT'])
def inject_oir():
    volume = request.get_json()
    try:
        dss.conflict_manager.check_restrictions(volume)
        dss.scd.check_strategic_conflicts(volume)
        oir = {}
        oir["operational_intent"] = {}
        oir["operational_intent"]["reference"] = dss.scd.put_operational_intent(volume)
        oir["operational_intent"]["details"] = {
            "volumes": [],
            "off_nominal_volumes": [],
            "priority": 0
        }
        oir["operational_intent"]["details"]["volumes"].append(volume)
        database[oir["operational_intent"]["reference"]['id']] = oir


    except Exception as ex:
        print(f"Erro na criação: {ex}")
        return {"msg": "Erro"}, 400

    return {"Success": True}, 201


if __name__ == '__main__':
    app.run(port=5050)


```

</details><details id="bkmrk-dss.py-from-conflict"><summary>dss.py</summary>

```python
from conflict_manager import ConflictManager
from scd import Scd


class Dss:
    def __init__(self) -> None:
        self.conflict_manager = ConflictManager()
        self.scd = Scd()

```

</details><details id="bkmrk-scd.py-import-reques"><summary>scd.py</summary>

```python
import requests
import uuid

from env import USS_BASE_URL, DSS_HOST


class Scd:

    def __init__(self) -> None:
        self.auth()

    def auth(self):
        url = "http://kong.icea.decea.mil.br:64235/token?grant_type=client_credentials&intended_audience=localhost&issuer=localhost&scope={0}"
        self.strategic_coordination = requests.get(url.format("utm.strategic_coordination")).json()["access_token"]

    def check_strategic_conflicts(self, volume):
        url = DSS_HOST + "/dss/v1/operational_intent_references/query"
        body = {
            "area_of_interest": volume
        }
        header = {"authorization": f"Bearer {self.strategic_coordination}"}
        response = requests.post(url, headers=header, json=body).json()

        if (len(response['operational_intent_references']) > 0):
            raise Exception(f"Interseção com outra Intenção {response['operational_intent_references'][0]['id']}")
        else:
            print("Sem intenções para o volume")
        
    def put_operational_intent(self, volume):
        id = str(uuid.uuid4())
        url = DSS_HOST + f"/dss/v1/operational_intent_references/{id}"

        body = {
            "flight_type": "VLOS",
            "extents": [volume],
            "key": [],
            "state": "Accepted",
            "uss_base_url": USS_BASE_URL,
            "new_subscription": {
                "uss_base_url": USS_BASE_URL,
                "notify_for_constraint": False
            }
        }

        print(body)

        header = {"authorization": f"Bearer {self.strategic_coordination}"}

        response = requests.put(url, headers=header, json=body).json()

        print(f"OIR criada com id: {id}")
        print(response)

        return response['operational_intent_reference']


```

</details><details id="bkmrk-conflict_manager.py-"><summary>conflict\_manager.py</summary>

```python
import requests
import uuid

from env import USS_BASE_URL, DSS_HOST


class Scd:

    def __init__(self) -> None:
        self.auth()

    def auth(self):
        url = "http://kong.icea.decea.mil.br:64235/token?grant_type=client_credentials&intended_audience=localhost&issuer=localhost&scope={0}"
        self.strategic_coordination = requests.get(url.format("utm.strategic_coordination")).json()["access_token"]

    def check_strategic_conflicts(self, volume):
        url = DSS_HOST + "/dss/v1/operational_intent_references/query"
        body = {
            "area_of_interest": volume
        }
        header = {"authorization": f"Bearer {self.strategic_coordination}"}
        response = requests.post(url, headers=header, json=body).json()

        if (len(response['operational_intent_references']) > 0):
            raise Exception(f"Interseção com outra Intenção {response['operational_intent_references'][0]['id']}")
        else:
            print("Sem intenções para o volume")
        
    def put_operational_intent(self, volume):
        id = str(uuid.uuid4())
        url = DSS_HOST + f"/dss/v1/operational_intent_references/{id}"

        body = {
            "flight_type": "VLOS",
            "extents": [volume],
            "key": [],
            "state": "Accepted",
            "uss_base_url": USS_BASE_URL,
            "new_subscription": {
                "uss_base_url": USS_BASE_URL,
                "notify_for_constraint": False
            }
        }

        print(body)

        header = {"authorization": f"Bearer {self.strategic_coordination}"}

        response = requests.put(url, headers=header, json=body).json()

        print(f"OIR criada com id: {id}")
        print(response)

        return response['operational_intent_reference']


```

</details>