> 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 genera ningún valor cuando falta un valor que necesita, y qué patrones de comparación lo evitan.

Las fórmulas y condiciones en IoT Logic trabajan con los valores que envía un dispositivo GPS. Cuando falta un valor que una fórmula necesita, la mayoría de los operadores no pueden producir un resultado, y la fórmula no produce nada en absoluto: no `falso`, y no cero. Esta página explica cuándo falta un valor, cómo se ve la falla y cómo escribir fórmulas y condiciones que sigan funcionando. Está dirigida a cualquier persona que configure un flujo de IoT Logic, y no supone conocimientos de programación.

La página se aplica a ambos lugares donde usted 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 se 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 luego tiene que trabajar con el valor vacío. Un solo valor vacío detiene toda la expresión, incluidas las partes que 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 marca la falla. El resultado depende de qué nodo contiene la expresión:

| Dónde se ejecuta la expresión                                         | Qué ocurre 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 marca la falla. No aparece ningún error en el flujo, ningún contador cambia y todos los demás atributos siguen calculándose normalmente. La única señal es el propio valor faltante, por lo que un flujo puede parecer en buen estado mientras un atributo no produce ningún valor durante semanas.

Guardar un flujo tampoco demuestra 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 con los datos de su dispositivo GPS, así que una fórmula que no produce nada en cada paquete se sigue guardando 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 que se lee primero determina la respuesta. Todos los demás operadores se detienen.

Esta tabla cubre un atributo al que usted hace referencia por nombre, que es la forma que [autocompletado](/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. Consulte [Lectura por nombre o con value()](#reading-by-name-or-with-value).

| Operador                                                         | Con un valor vacío en cualquiera de los lados                                                                  |
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `==`, `!=` (igual a, distinto de)                                | Devuelve un sí o no real. `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 no real. 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 por `falso`, por `0`, y por texto vacío.                    |
| `a ? b : c` (elegir entre dos valores)                           | Toma la `c` rama, igual que lo hace para `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 que se lee primero determine la respuesta.                   |

Los seis operadores de texto se dividen en dos. `=~` y `!~` tolera un valor vacío, pero `=^`, `!^`, `=$`, y `!$` no lo haga cuando el atributo se referencia 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 `math:` 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` aún producen un resultado cuando falta uno de sus argumentos. Al unir texto con `+` no es tolerante: `'Zone: ' + zone_label` no produce nada.

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

El orden importa en 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 resultado de 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 determina el resultado de OR, por lo que el lado derecho nunca se lee. |
| `false \|\| (vacío)`          | No produce nada.                                                                                           |
| `(vacío) \|\| cualquier cosa` | 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, en su lugar, compare el valor de forma explícita.

## Lectura por nombre o con value()

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

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

Referenciar el atributo por nombre es la forma en que [autocompletado](/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 `!$` informar `true` en un paquete que no lleva 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 de ninguna manera, y `==`, `!=`, `=~` y `!~` todos dan un sí o un no real, de una forma u otra.

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 `??` sobre un nombre sigue funcionando, porque antes de eso no ocurre ningún cálculo. Solo un cálculo envuelto dentro de `??` o `? :` se comporta de manera diferente.

## Compare un valor explícitamente

Para hacer seguro en una condición un valor que podría estar vacío, compárelo con `== true` o `== false` en lugar de usarlo por sí solo. Ambas `==` y `!=` dan un sí o no real para un valor vacío, de modo que un término que no tiene datos ya no detiene 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 funcionan de la misma manera, porque devuelven un valor vacío cuando un paquete no lleva posición. Esta condición se detiene tan pronto como una función no puede responder:

```jexl
leaveGeofence(51577 /* almacén de Austin */) || leaveGeofence(85269 /* sitio de construcción 1 */)
```

Esta condición prueba ambas Zonas en cada paquete:

```jexl
leaveGeofence(51577 /* Almacén de Austin */) == true || leaveGeofence(85269 /* Sitio de construcción 1 */) == true
```

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

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

{% hint style="warning" %}
No use `!` sobre un valor que podría estar vacío. `!inZona(35229)` no produce nada cuando la posición es desconocida, así que no puede detectar un dispositivo fuera de la Zona. Escriba `inZona(35229) == false` para «sabido que está fuera», o `inZona(35229) != true` para "no se sabe que esté 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 incluye el atributo, aunque un paquete anterior sí lo hizo.
* La posición del historial que solicitó con `value()` todavía 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 eliminó su historial almacenado. Vea [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 un nombre para 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 gestionar 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 la protección primero. La protección usa `!=`, lo que da un sí o un no real para un valor vacío, de modo que la propia validación 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 ejecuta 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` falta, 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 `??` se ven similares y se comportan de manera diferente. `??` sustituye el lado derecho solo para 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 reporta `true` cuando la ignición está realmente apagada. Use `??` cuando quiera decir "si falta el valor".
{% endhint %}

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

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

Cuando no hay valor, es mejor que uno incorrecto; un atributo sin valor es el resultado correcto. Agregue un valor de respaldo solo cuando un sistema más adelante en el flujo necesite un valor en cada paquete.

## Compruebe si una expresión no produce ningún valor

Trabaje con 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** interruptor. Un cálculo fallido aparece como un `null` valor. El interruptor oculta esos valores cuando está activado.
3. Aumente la profundidad si el paquete que busca 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` apunta a 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 podría estar vacía. Use `== true`, `== false`, o un `??` 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 está `falso` almacena `falso`, y una condición que no se pudo evaluar 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 dice qué ocurrió. Una expresión posterior que prueba 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 sigue funcionando para los demás?

Los dispositivos de distintos modelos no envían todos 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 lee ese atributo sin una comparación no produce nada solo para ese dispositivo. Compare cada término explícitamente con `== true` o `== false`.

## Ver 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 saber qué rama toma un nodo Logic y qué almacena.
* [Funciones de zonas](/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()` la 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
