> 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/es/guide/account/iot-logic/nodes/missing-values-in-expressions.md).

# Valores faltantes en expresiones

Comprenda por qué una fórmula o condición de IoT Logic no produce ningún valor cuando falta un valor que necesita, y qué patrones de comparación lo impiden.

Las fórmulas y condiciones en IoT Logic funcionan con los valores que envía un dispositivo GPS. Cuando falta un valor que necesita una fórmula, la mayoría de los operadores no pueden producir un resultado, y la fórmula no produce absolutamente nada: nulo `falso`, y no cero. Esta página explica cuándo un valor desaparece, qué aspecto tiene la falla y cómo escribir fórmulas y condiciones que sigan funcionando. Está dirigida a cualquiera que configura un flujo de IoT Logic, y no supone conocimientos de programación.

La página se aplica a ambos lugares donde escribe una expresión: el **Fórmula** campo de un [Iniciar atributo](/docs/user/es/guide/account/iot-logic/nodes/initiate-attribute-node.md) nodo, y el **Expresión de condición (JEXL)** campo de un [IF/THEN Lógica](/docs/user/es/guide/account/iot-logic/nodes/logic-node.md) nodo.

## Cuando una expresión no puede producir un valor

Un valor vacío detiene toda la expresión. Eso aplica a cualquiera de los lados de un cálculo, una comparación de tamaño, una prueba de prefijo de texto o un operador lógico `!`, `&&`, o `||`. En una fórmula y en Analizador de datos, un valor vacío aparece como `null`.

Leer un atributo que un dispositivo GPS nunca ha enviado no es un error por sí mismo. Lo que se detiene es el operador que entonces debe trabajar con el valor vacío. Un solo valor vacío detiene toda la expresión, incluidas las partes que sí tenían valores. Una condición que prueba cuatro geocercas se detiene en la primera que no puede responder, y las otras tres nunca se prueban. La excepción es un término anterior en la expresión que ya ha determinado el resultado.

## Lo que ve cuando una expresión no produce nada

Nada indica la falla. El resultado depende de qué nodo contiene la expresión:

| Dónde se ejecuta la expresión                                         | Qué sucede con ese paquete de datos                                                                               |
| --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| **Fórmula** campo de un **Iniciar atributo** nodo                     | El atributo no tiene valor para ese paquete, y Analizador de datos lo muestra como `null`.                        |
| **Expresión de condición (JEXL)** campo de un **IF/THEN Lógica** nodo | Los datos salen por la conexión ELSE, y el nodo almacena su propio atributo como un valor vacío, no como `falso`. |

{% hint style="warning" %}
Nada informa la falla. No aparece ningún error en el flujo, no cambia ningún contador y todos los demás atributos siguen calculándose normalmente. La única señal es el valor faltante en sí, así que un flujo puede parecer correcto mientras un atributo no produce ningún valor durante semanas.

Guardar un flujo tampoco prueba que una fórmula funcione. La comprobación que se ejecuta al guardar confirma que la expresión está escrita correctamente. No ejecuta la expresión contra los datos de su dispositivo GPS, así que una fórmula que no produce nada en cada paquete todavía se guarda sin una advertencia.
{% endhint %}

## Cómo maneja cada operador un valor vacío

Cuatro operadores siempre siguen funcionando con un valor vacío: `==`, `!=`, `=~`, y `!~`. Los operadores `&&` y `||` siguen funcionando solo cuando el lado leído primero ya determina la respuesta. Todo otro operador se detiene.

Esta tabla cubre un atributo al que hace referencia por nombre, que es la forma que [autorrelleno](/docs/user/es/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#autofill-attribute-names) inserta. Cuatro operadores se comportan de manera diferente cuando el valor proviene de `value()` en su lugar. Vea [Leer por nombre o con value()](#reading-by-name-or-with-value).

| Operador                                                         | Con un valor vacío a cualquiera de los lados                                                                        |
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `==`, `!=` (igual a, diferente de)                               | Devuelve un sí o un no reales. `null == null` es `true`, y `null != null` es `falso`.                               |
| `=~`, `!~` (está en una lista o coincide con un patrón de texto) | Devuelve un sí o un no reales. Un valor vacío nunca coincide, así que `=~` devuelve `falso` y `!~` devuelve `true`. |
| `??` (usar un valor de respaldo)                                 | Devuelve el valor de la derecha. Sustituye solo un valor vacío.                                                     |
| `?:` (usar un valor de respaldo)                                 | Devuelve el valor de la derecha. También sustituye `falso`por `0`y por texto vacío.                                 |
| `a ? b : c` (elegir entre dos valores)                           | Toma la `c` rama, igual que ocurre con `falso`.                                                                     |
| `=^`, `!^`, `=$`, `!$` (empieza con, termina con)                | La expresión no produce nada.                                                                                       |
| `<`, `<=`, `>`, `>=` (comparaciones de tamaño)                   | La expresión no produce nada.                                                                                       |
| `+`, `-`, `*`, `/`, `%` (aritmética)                             | La expresión no produce nada.                                                                                       |
| `&`, `\|`, `^` (operaciones bit a bit)                           | La expresión no produce nada.                                                                                       |
| `!` (no)                                                         | La expresión no produce nada.                                                                                       |
| `&&`, `\|\|` (y, o)                                              | La expresión no produce nada, a menos que el lado leído primero ya determine la respuesta.                          |

Los seis operadores de texto se dividen en dos. `=~` y `!~` sobreviven a un valor vacío, pero `=^`, `!^`, `=$`, y `!$` no lo hacen cuando se hace referencia al atributo por nombre. Una condición como `hardware_key !^ 'AB'` parece una forma segura de excluir un prefijo, pero no produce nada en cada paquete sin `hardware_key`.

El `matemáticas:` las funciones no producen nada cuando reciben un valor vacío, así que `math:round(engine_temp)` no produce nada cuando `engine_temp` falta. El `util:` las funciones son más tolerantes y devuelven un valor vacío en su lugar, por lo que `util:join` y `util:joinNonNull` siguen produciendo un resultado cuando uno de sus argumentos falta. Unir texto con `+` no es tolerante: `'Zone: ' + zone_label` no produce nada.

## Operadores lógicos con un valor vacío

El orden importa para ambos `&&` y `||`. Cada operador lee primero el lado izquierdo y se detiene allí cuando el lado izquierdo ya determina el resultado. Un `falso` el lado izquierdo determina el resultado `&&`, y un `true` el lado izquierdo determina el resultado `||`.

| Expresión                      | Resultado                                                                                             |
| ------------------------------ | ----------------------------------------------------------------------------------------------------- |
| `false && (vacío)`             | `falso`. Un lado izquierdo falso determina el AND, por lo que el lado derecho nunca se lee.           |
| `true && (vacío)`              | No produce nada.                                                                                      |
| `(vacío) && cualquier cosa`    | No produce nada. El lado izquierdo se lee primero.                                                    |
| `true \|\| (vacío)`            | `true`. Un lado izquierdo verdadero fija el resultado de OR, por lo que el lado derecho nunca se lee. |
| `falso \|\| (vacío)`           | No produce nada.                                                                                      |
| `(vacío) \|\| cualquier valor` | No produce nada. El lado izquierdo se lee primero.                                                    |

Colocar al final el término que podría estar vacío solo ayuda cuando el lado izquierdo determina el resultado en ese paquete. Rara vez puede garantizar ese resultado, así que compare el valor de forma explícita en su lugar.

## Leer por nombre o con value()

Cuatro operadores dan resultados diferentes para el mismo valor faltante, según cómo la fórmula lo interprete. Los operadores son `=^`, `!^`, `=$` y `!$`, los que prueban el inicio o el final de un valor de texto.

| Fórmula                                | Resultado cuando `id_del_conductor` nunca se envió |
| -------------------------------------- | -------------------------------------------------- |
| `id_del_conductor !^ 'AB'`             | No produce nada                                    |
| `value('driver_id', 0, 'all') !^ 'AB'` | `true`                                             |

Referenciar el atributo por nombre es el Formulario que [autorrelleno](/docs/user/es/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#autofill-attribute-names) inserciones, por lo que una condición creada con el selector de atributos toma la primera ruta. Escriba la comparación con `value()` cuando necesite `!^` o `!$` reportar `true` en un paquete que no contiene el atributo.

Todos los demás operadores se comportan igual en ambas formas. Una comparación de tamaño, aritmética y `!` todos no producen nada en ningún caso, y `==`, `!=`, `=~` y `!~` todos dan un sí o un no real de cualquier manera.

La misma división se aplica a los dos formularios de respaldo. `??` y `? :` puede contener un cálculo fallido cuando el valor proviene de `value()`, y no puede cuando proviene de un nombre:

| Fórmula                                  | Resultado cuando `Odómetro` nunca se envió |
| ---------------------------------------- | ------------------------------------------ |
| `(Odómetro + 1) ?? 0`                    | No produce nada                            |
| `(value('Odómetro', 0, 'all') + 1) ?? 0` | `0`                                        |

Un simple `??` en un nombre sigue funcionando, porque no se realiza ningún cálculo antes. Solo un cálculo incluido dentro de `??` o `? :` se comporta de manera diferente.

## Comparar un valor explícitamente

Para que un valor que podría estar vacío sea seguro en una condición, compárelo con `== true` o `== false` en lugar de usarlo por sí solo. Ambos `==` y `!=` Devuelva un valor real de sí o no para un valor vacío, de modo que un término sin datos ya no detenga toda la condición.

Esta condición se detiene en cualquier paquete en el que falte uno de los dos atributos:

```jexl
door_open || hood_open
```

Esta condición sigue funcionando y devuelve sí cuando cualquiera de las puertas está abierta:

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

Las funciones de zona se comportan igual, porque devuelven un valor vacío cuando un paquete no contiene posición. Esta condición se detiene en cuanto una función no puede responder:

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

Esta condición prueba ambas zonas en cada paquete:

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

Elija la comparación que coincida con lo que debe contar como un paquete sin datos:

* `== true` significa «se sabe que es sí». Un valor vacío da `falso`, así que un paquete sin datos no coincide.
* `== false` significa «se sabe que no». Un valor vacío da `falso`, así que un paquete sin datos no coincide.
* `!= true` significa «no se sabe que sea sí». Un valor vacío da `true`, así que un paquete sin datos sí coincide.

{% hint style="warning" %}
No use `!` en un valor que podría estar vacío. `!inGeofence(35229)` no produce nada cuando la posición es desconocida, así que no puede detectar un dispositivo fuera de la Zona. Escriba `inGeofence(35229) == false` para "conocido por estar fuera", o `inGeofence(35229) != true` para "no conocido por estar dentro".
{% endhint %}

## De dónde provienen los valores vacíos

Un atributo en una fórmula se resuelve en un valor vacío en estos casos:

* El atributo nunca se ha enviado para ese dispositivo GPS.
* El paquete actual no contiene el atributo, aunque un paquete anterior sí lo hizo.
* La posición del historial que solicitó con `value()` aún no existe, porque el dispositivo ha enviado menos paquetes de los que requiere la posición.
* El dispositivo no envió nada durante más de 30 días, por lo que Navixy descartó su historial almacenado. Consulte [Sintaxis completa](/docs/user/es/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#full-syntax).
* `inGeofence()`, `enterGeofence()`, o `leaveGeofence()` no puede responder, porque el paquete no contiene coordenadas o la Zona ya no existe en la cuenta. Vea [Cuando una función de zona no da respuesta](/docs/user/es/guide/account/iot-logic/nodes/geofence-functions.md#when-a-geofence-function-gives-no-answer).
* `geofenceName()` no tiene nombre que devolver. Vea [Lo que devuelve](/docs/user/es/guide/account/iot-logic/nodes/geofence-functions.md#what-you-get-back).

Todas estas causas se ven igual en una fórmula. Una fórmula que debe seguir funcionando tiene que manejar el valor vacío en lugar de la causa.

## Fórmulas que siempre deben producir un valor

Guarde el cálculo con `!= null`, y coloque primero el guardia. El guardia usa `!=`, lo que da un sí o no real para un valor vacío, por lo que la validación en sí nunca se detiene:

```jexl
value('odometer', 0, 'all') != null && value('odometer', 0, 'all') > 100
```

El orden es lo que hace que la guarda funcione. Si invierte los términos, la comparación se evalúa antes que la guarda, y toda la condición no produce nada.

Para sustituir un valor alternativo en su lugar, use `??`. Devuelve el lado derecho solo cuando el lado izquierdo está vacío:

```jexl
can_speed ?? 0
```

`??` sustituye un valor faltante, no un cálculo fallido. `(can_speed * 1.1) ?? 0` no produce nada cuando `can_speed` está ausente, porque la multiplicación se detiene antes de `??` alcanzarse. Coloque `??` alrededor del atributo en lugar de alrededor del cálculo:

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

{% hint style="warning" %}
`?:` y `??` parecen similares y se comportan de forma diferente. `??` sustituye el lado derecho solo por un valor vacío. `?:` lo sustituye por un valor vacío y también por `falso`por `0`, y para texto vacío. La fórmula `ignición ?: true` por lo tanto, reportes `true` cuando la ignición está realmente apagada. Use `??` cuando quiera decir «si falta el valor».
{% endhint %}

También puede condicionar el cálculo fuera de la fórmula. Coloque un **IF/THEN Lógica** nodo antes del **Iniciar atributo** nodo y pruebe la presencia de los atributos en su condición. Conecte la ruta THEN al nodo de cálculo, de modo que reciba solo paquetes que contengan los valores que necesita.

Conecte la ruta ELSE a un **Nodo de Salida** nodo también. Una rama que termina sin uno descarta todos los paquetes que llegan a ella, por lo que los paquetes que no superaron la prueba de presencia nunca salen del flujo.

Cuando ningún valor es mejor que uno incorrecto, un atributo sin valor es el resultado correcto. Añada un valor de reserva solo cuando un sistema más adelante en el flujo necesite un valor en cada paquete.

## Compruebe si una expresión no produce nada

Trabaje a partir de lo que puede ver en [Analizador de datos](/docs/user/es/guide/account/iot-logic/data-stream-analyzer.md):

1. Seleccione el flujo, luego el dispositivo GPS y el atributo calculado.
2. Desactive el **Excluir nulos** conmutador. Un cálculo fallido aparece como un `null` valor. El conmutador oculta esos valores cuando está activado.
3. Aumente la profundidad si el paquete que está buscando es más antiguo que los valores en pantalla.
4. Compare el atributo con los atributos que lee su fórmula. Un paquete en el que las entradas de la fórmula tienen valores y el atributo calculado es `null` señala la fórmula.
5. Compruebe cada operador de la fórmula con respecto a [Cómo maneja cada operador un valor vacío](#how-each-operator-handles-an-empty-value).
6. Reescriba cada parte que pueda estar vacía. Use `== true`, `== false`, o un `??` valor de respaldo.

{% hint style="warning" %}
Cuando **Excluir nulos** está activado, el último valor que produjo la fórmula permanece en pantalla con su propia marca de tiempo anterior. La lectura parece actual, pero pertenece a un paquete anterior. Desactive el interruptor antes de juzgar si IoT Logic sigue calculando un atributo.
{% endhint %}

## Preguntas frecuentes

#### ¿Un valor vacío es lo mismo que `falso`?

No. Una condición que realmente `falso` almacena `falso`, y una condición que no pudo evaluarse almacena un valor vacío. Ambas envían los datos a través de la conexión ELSE de un **IF/THEN Lógica** nodo, por lo que la rama por sí sola no le indica cuál ocurrió. Una expresión posterior que comprueba el atributo con `my_flag == false` solo coincide con el primer caso.

#### ¿Por qué un dispositivo GPS dejó de coincidir con una condición que aún funciona para los demás?

Los dispositivos de distintos modelos no siempre envían los mismos atributos, y un dispositivo puede dejar de reportar un atributo que los demás aún envían. Entonces, una condición que lea ese atributo sin una comparación no produce nada solo para ese dispositivo. Compare explícitamente cada término con `== true` o `== false`.

## Vea también

* [Expresiones y sintaxis de IF/THEN Lógica](/docs/user/es/guide/account/iot-logic/nodes/logic-node/logic-node-expressions-and-syntax.md#missing-values-and-null-routing) para qué rama toma un nodo lógico y qué almacena.
* [Funciones de zona](/docs/user/es/guide/account/iot-logic/nodes/geofence-functions.md) para los casos en que una función de zona no puede responder.
* [Administrar atributos](/docs/user/es/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#expression-language) para el `value()` función y las dos opciones de sintaxis.
* [Ejemplos de cálculo](/docs/user/es/guide/account/iot-logic/nodes/initiate-attribute-node/calculation-examples.md) para ejemplos 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/es/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.
