> For the complete documentation index, see [llms.txt](https://navixy.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://navixy.com/docs/user/pt-br/guide/account/iot-logic/nodes/missing-values-in-expressions.md).

# Valores ausentes em expressões

Entenda por que uma fórmula ou condição do IoT Logic não produz valor quando falta um valor de que ela precisa, e quais padrões de comparação o evitam.

Fórmulas e condições no IoT Logic funcionam com os valores que um dispositivo GPS envia. Quando um valor de que uma fórmula precisa está ausente, a maioria dos operadores não consegue produzir um resultado, e a fórmula não produz nada: nem `false`, e não zero. Esta página explica quando um valor fica ausente, como a falha se manifesta e como escrever fórmulas e condições que continuam funcionando. Ela é destinada a qualquer pessoa que configure um fluxo do IoT Logic e não pressupõe conhecimento de programação.

A página se aplica aos dois locais em que você escreve uma expressão: o **Fórmula** campo de um [Iniciar Atributo](/docs/user/pt-br/guide/account/iot-logic/nodes/initiate-attribute-node.md) nó e o **campo Expressão de condição (JEXL)** campo de um [Lógica](/docs/user/pt-br/guide/account/iot-logic/nodes/logic-node.md) nó.

## Quando uma expressão não consegue produzir um valor

Um valor vazio interrompe a expressão inteira. Isso se aplica a qualquer lado de um cálculo, de uma comparação de tamanho, de um teste de prefixo de texto ou de uma operação lógica `!`, `&&`, ou `||`. Em uma fórmula e no Analisador de dados, um valor vazio aparece como `null`.

Ler um atributo que um dispositivo GPS nunca enviou não é, por si só, um erro. O que é interrompido é o operador que então precisa trabalhar com o valor vazio. Um único valor vazio interrompe a expressão inteira, inclusive as partes que tinham valores. Uma condição que testa quatro geocercas para na primeira que não consegue responder, e as outras três nunca são testadas. A exceção é um termo anterior na expressão que já tenha definido o resultado.

## O que você vê quando uma expressão não produz nada

Nada indica a falha. O resultado depende de qual nó contém a expressão:

| Onde a expressão é executada                                     | O que acontece com esse pacote de dados                                                                        |
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| **Fórmula** campo de um **Iniciar Atributo** nó                  | O atributo não tem valor para esse pacote, e o Analisador de dados o mostra como `null`.                       |
| **campo Expressão de condição (JEXL)** campo de um **Lógica** nó | Os dados saem pela conexão ELSE, e o nó armazena seu próprio atributo como um valor vazio, e não como `false`. |

{% hint style="warning" %}
Nada informa a falha. Nenhum erro aparece no fluxo, nenhum contador muda, e todos os outros atributos ainda são calculados normalmente. O único sinal é o próprio valor ausente; assim, um fluxo pode parecer saudável enquanto um atributo não produz valor por semanas.

Salvar um fluxo também não prova que uma fórmula funciona. A verificação executada quando você salva confirma que a expressão foi escrita corretamente. Ela não executa a expressão com os dados do seu dispositivo GPS, então uma fórmula que não produz nada em cada pacote ainda é salva sem aviso.
{% endhint %}

## Como cada operador lida com um valor vazio

Quatro operadores continuam funcionando sempre com um valor vazio: `==`, `!=`, `=~`, e `!~`. Os operadores `&&` e `||` continuam funcionando somente quando o lado lido primeiro define a resposta. Todos os outros operadores param.

Esta tabela aborda um atributo ao qual você faz referência pelo nome, que é o formato que [preenchimento automático](/docs/user/pt-br/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#autofill-attribute-names) insere. Quatro operadores se comportam de forma diferente quando o valor vem de `value()` em vez disso. Veja [Ler pelo nome ou com value()](#reading-by-name-or-with-value).

| Operador                                                           | Com um valor vazio em qualquer lado                                                                          |
| ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
| `==`, `!=` (igual a, diferente de)                                 | Gera um verdadeiro sim ou não. `null == null` é `true`, e `null != null` é `false`.                          |
| `=~`, `!~` (está em uma lista ou corresponde a um padrão de texto) | Gera um verdadeiro sim ou não. Um valor vazio nunca corresponde, então `=~` gera `false` e `!~` gera `true`. |
| `??` (usar um valor alternativo)                                   | Fornece o valor à direita. Ele substitui apenas um valor vazio.                                              |
| `?:` (usar um valor alternativo)                                   | Fornece o valor à direita. Ele também substitui `false`, por `0`, e por texto vazio.                         |
| `a ? b : c` (escolher entre dois valores)                          | Toma o `c` ramo, da mesma forma que faz para `false`.                                                        |
| `=^`, `!^`, `=$`, `!$` (começa com, termina com)                   | A expressão não produz nada.                                                                                 |
| `<`, `<=`, `>`, `>=` (comparações de tamanho)                      | A expressão não produz nada.                                                                                 |
| `+`, `-`, `*`, `/`, `%` (aritmética)                               | A expressão não produz nada.                                                                                 |
| `&`, `\|`, `^` (operações bit a bit)                               | A expressão não produz nada.                                                                                 |
| `!` (não)                                                          | A expressão não produz nada.                                                                                 |
| `&&`, `\|\|` (e, ou)                                               | A expressão não produz nada, a menos que o lado lido primeiro defina a resposta.                             |

Os seis operadores de texto se dividem em dois. `=~` e `!~` sobrevive a um valor vazio, mas `=^`, `!^`, `=$`, e `!$` não, quando o atributo é referenciado pelo nome. Uma condição como `hardware_key !^ 'AB'` parece uma maneira segura de excluir um prefixo, mas não produz nada em todo pacote sem `hardware_key`.

O `matemática:` as funções não produzem nada quando recebem um valor vazio, então `matemática:round(engine_temp)` não produz nada quando `engine_temp` está ausente. A `util:` funções são mais tolerantes e retornam um valor vazio em vez disso, então `util:join` e `util:joinNonNull` ainda produzem um resultado quando um de seus argumentos está ausente. Concatenar texto com `+` não é tolerante: `'Zona: ' + zone_label` não produz nada.

## Operadores lógicos com um valor vazio

A ordem importa para ambos `&&` e `||`. Cada operador lê o lado esquerdo primeiro e para ali quando o lado esquerdo já determina o resultado. Um `false` o lado esquerdo determina o resultado `&&`, e um `true` o lado esquerdo determina o resultado `||`.

| Expressão                     | Resultado                                                                             |
| ----------------------------- | ------------------------------------------------------------------------------------- |
| `falso && (vazio)`            | `false`. Um lado esquerdo falso determina o AND, então o lado direito nunca é lido.   |
| `verdadeiro && (vazio)`       | Não produz nada.                                                                      |
| `(vazio) && qualquer coisa`   | Não produz nada. O lado esquerdo é lido primeiro.                                     |
| `verdadeiro \|\| (vazio)`     | `true`. Um lado esquerdo verdadeiro resolve um OR, então o lado direito nunca é lido. |
| `falso \|\| (vazio)`          | Não produz nada.                                                                      |
| `(vazio) \|\| qualquer coisa` | Não produz nada. O lado esquerdo é lido primeiro.                                     |

Colocar o termo que pode estar vazio por último ajuda apenas quando o lado esquerdo define o resultado naquele pacote. Você raramente consegue garantir esse resultado, então compare o valor explicitamente em vez disso.

## Ler pelo nome ou com value()

Quatro operadores produzem resultados diferentes para o mesmo valor ausente, dependendo de como a fórmula o lê. Os operadores são `=^`, `!^`, `=$` e `!$`, as que testam o início ou o fim de um valor de texto.

| Fórmula                                | Resultado quando `motorista_id` nunca foi enviado |
| -------------------------------------- | ------------------------------------------------- |
| `id do motorista !^ 'AB'`              | Não produz nada                                   |
| `value('driver_id', 0, 'all') !^ 'AB'` | `true`                                            |

Referenciar o atributo pelo nome é o Formulário que [preenchimento automático](/docs/user/pt-br/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#autofill-attribute-names) insere, portanto, uma condição criada com o seletor de atributos segue o primeiro caminho. Escreva a comparação com `value()` quando você precisar `!^` ou `!$` relatar `true` em um pacote que não contém o atributo.

Todos os outros operadores se comportam da mesma forma em ambas as formas. Uma comparação de tamanho, aritmética e `!` todos não geram nada de qualquer forma, e `==`, `!=`, `=~` e `!~` todos dão um sim ou não de verdade, de um jeito ou de outro.

A mesma divisão se aplica às duas formas de fallback. `??` e `? :` pode conter um cálculo com falha quando o valor vem de `value()`, e não pode quando ele vem de um nome:

| Fórmula                                  | Resultado quando `odômetro` nunca foi enviado |
| ---------------------------------------- | --------------------------------------------- |
| `(odômetro + 1) ?? 0`                    | Não produz nada                               |
| `(value('odômetro', 0, 'all') + 1) ?? 0` | `0`                                           |

Uma simples `??` em um nome ainda funciona, porque não há cálculo antes dele. Apenas um cálculo envolvido por `??` ou `? :` se comporta de forma diferente.

## Comparar um valor explicitamente

Para tornar seguro em uma condição um valor que pode estar vazio, compare-o com `== true` ou `== false` em vez de usá-lo sozinho. Ambos `==` e `!=` fornecem um verdadeiro sim ou não para um valor vazio, de modo que um termo sem dados não interrompe mais a condição inteira.

Esta condição para em qualquer pacote em que um dos dois atributos esteja ausente:

```jexl
door_open || hood_open
```

Esta condição continua funcionando e retorna sim quando qualquer uma das portas está aberta:

```jexl
door_open == true || hood_open == true
```

As funções de geocerca se comportam da mesma forma, porque retornam um valor vazio quando um pacote não traz posição. Esta condição para assim que uma função não consegue responder:

```jexl
leaveGeofence(51577 /* Austin Warehouse */) || leaveGeofence(85269 /* Construction site 1 */)
```

Esta condição testa as duas geocercas em cada pacote:

```jexl
leaveGeofence(51577 /* Armazém de Austin */) == true || leaveGeofence(85269 /* Canteiro de obras 1 */) == true
```

Escolha a comparação que corresponda ao que um pacote sem dados deve contar como:

* `== true` significa "sabidamente sim". Um valor vazio gera `false`, então um pacote sem dados não corresponde.
* `== false` significa "sabidamente não". Um valor vazio gera `false`, então um pacote sem dados não corresponde.
* `!= true` significa "não sabidamente sim". Um valor vazio gera `true`, então um pacote sem dados corresponde.

{% hint style="warning" %}
Não use `!` em um valor que possa estar vazio. `!inGeofence(35229)` não produz nada quando a posição é desconhecida, então não consegue detectar um dispositivo fora da geocerca. Escreva `inGeofence(35229) == false` para "sabidamente fora", ou `inGeofence(35229) != true` para "não sabidamente dentro".
{% endhint %}

## De onde vêm os valores vazios

Um atributo em uma fórmula resulta em um valor vazio nestes casos:

* O atributo nunca foi enviado para esse dispositivo GPS.
* O pacote atual não traz o atributo, embora um pacote anterior trouxesse.
* A posição do histórico que você solicitou com `value()` ainda não existe, porque o dispositivo enviou menos pacotes do que a posição exige.
* O dispositivo não enviou nada por mais de 30 dias, então a Navixy descartou o histórico armazenado. Veja [Sintaxe completa](/docs/user/pt-br/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#full-syntax).
* `inGeofence()`, `enterGeofence()`, ou `leaveGeofence()` não consegue responder, porque o pacote não traz coordenadas ou a geocerca não existe mais na conta. Veja [Quando uma função de geocerca não fornece resposta](/docs/user/pt-br/guide/account/iot-logic/nodes/geofence-functions.md#when-a-geofence-function-gives-no-answer).
* `geofenceName()` não tem nome para retornar. Veja [O que você recebe de volta](/docs/user/pt-br/guide/account/iot-logic/nodes/geofence-functions.md#what-you-get-back).

Todas essas causas parecem iguais em uma fórmula. Uma fórmula que precisa continuar funcionando deve tratar o valor vazio, e não a causa.

## Fórmulas que devem sempre produzir um valor

Proteja o cálculo com `!= null`, e coloque a proteção primeiro. A proteção usa `!=`, o que gera

```jexl
value('odômetro', 0, 'all') != null && value('odômetro', 0, 'all') > 100
```

A ordem é o que faz a proteção funcionar. Se você inverter os termos, a comparação é executada antes da proteção, e a condição inteira não produz nada.

Para substituir um valor de fallback em vez disso, use `??`. Ele retorna a parte da direita somente quando a parte da esquerda está vazia:

```jexl
can_speed ?? 0
```

`??` substitui um valor ausente, não um cálculo malsucedido. `(can_speed * 1.1) ?? 0` não produz nada quando `can_speed` está ausente, porque a multiplicação para antes de `??` ser alcançada. Coloque `??` em torno do atributo, em vez de em torno do cálculo:

```jexl
(can_speed ?? 0) * 1.1
```

{% hint style="warning" %}
`?:` e `??` parecem semelhantes e se comportam de forma diferente. `??` substitui o lado direito apenas para um valor vazio. `?:` substitui-o por um valor vazio e também por `false`, por `0`, e por texto vazio. A fórmula `ignição ?: true` portanto, indica `true` quando a ignição está realmente desligada. Use `??` quando você quiser dizer "se o valor estiver ausente".
{% endhint %}

Você também pode condicionar o cálculo de fora da fórmula. Coloque um **Lógica** nó antes do **Iniciar Atributo** nó, e verifique a presença dos atributos em sua condição. Conecte o caminho THEN ao nó de cálculo, para que ele receba apenas pacotes que contenham os valores de que precisa.

Conecte o caminho ELSE a um **Ponto de Extremidade de Saída** Nó também. Um ramo que termina sem um Nó descarta todos os pacotes que chegam a ele, então os pacotes que falharam no teste de presença nunca saem do fluxo.

Quando nenhum valor é melhor do que um valor incorreto, um atributo sem valor é o resultado correto. Adicione um fallback somente quando um sistema mais adiante no fluxo precisar de um valor em cada pacote.

## Verifique se uma expressão não produz nada

Trabalhe com o que você pode ver em [Analisador de dados](/docs/user/pt-br/guide/account/iot-logic/data-stream-analyzer.md):

1. Selecione o fluxo, depois o dispositivo GPS e o atributo calculado.
2. Desative a **Excluir nulos** alternância. Uma falha de cálculo aparece como um `null` valor. A alternância oculta esses valores quando está ativada.
3. Aumente a profundidade se o pacote que você procura for mais antigo do que os valores na tela.
4. Compare o atributo com os atributos que sua fórmula lê. Um pacote em que as entradas da fórmula têm valores e o atributo calculado está `null` apontando para a fórmula.
5. Verifique cada operador na fórmula em relação a [Como cada operador lida com um valor vazio](#how-each-operator-handles-an-empty-value).
6. Reescreva cada parte que possa estar vazia. Use `== true`, `== false`, ou uma `??` alternativa.

{% hint style="warning" %}
Quando **Excluir nulos** estiver ativado, o último valor que a fórmula produziu permanece na tela com seu próprio carimbo de data e hora mais antigo. A leitura parece atual, mas pertence a um pacote anterior. Desative o botão de alternância antes de julgar se IoT Logic ainda calcula um atributo.
{% endhint %}

## Perguntas frequentes

#### Um valor vazio é o mesmo que `false`?

Não. Uma condição que é genuinamente `false` armazena `false`, e uma condição que não pôde ser avaliada armazena um valor vazio. Ambas enviam os dados pela conexão ELSE de um **Lógica** nó, então o ramo sozinho não informa o que aconteceu. Uma expressão posterior que testa o atributo com `my_flag == false` corresponde apenas ao primeiro caso.

#### Por que um dispositivo GPS deixou de corresponder a uma condição que ainda funciona para os outros?

Dispositivos de modelos diferentes nem sempre enviam os mesmos atributos, e um dispositivo pode parar de relatar um atributo que os outros ainda enviam. Uma condição que lê esse atributo sem uma comparação então não produz nada apenas para esse dispositivo. Compare cada termo explicitamente com `== true` ou `== false`.

## Veja também

* [Expressões e sintaxe da Lógica](/docs/user/pt-br/guide/account/iot-logic/nodes/logic-node/logic-node-expressions-and-syntax.md#missing-values-and-null-routing) qual ramo um Nó lógico segue e o que ele armazena.
* [Funções de geocerca](/docs/user/pt-br/guide/account/iot-logic/nodes/geofence-functions.md) para os casos em que uma função de geocerca não pode responder.
* [Gerenciamento de atributos](/docs/user/pt-br/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#expression-language) para o `value()` função e as duas opções de sintaxe.
* [Exemplos de cálculo](/docs/user/pt-br/guide/account/iot-logic/nodes/initiate-attribute-node/calculation-examples.md) para exemplos de fórmulas.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://navixy.com/docs/user/pt-br/guide/account/iot-logic/nodes/missing-values-in-expressions.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
