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

# Valeurs manquantes dans les expressions

Comprenez pourquoi une formule ou une condition IoT Logic ne produit aucune valeur lorsqu’une valeur nécessaire est manquante, et quels modèles de comparaison l’empêchent.

Les formules et les conditions dans IoT Logic fonctionnent sur les valeurs qu’envoie un appareil GPS. Lorsqu’une valeur dont une formule a besoin est manquante, la plupart des opérateurs ne peuvent pas produire de résultat, et la formule ne produit rien du tout : pas `false`, et non zéro. Cette page explique quand une valeur devient manquante, à quoi ressemble l’échec et comment écrire des formules et des conditions qui continuent de fonctionner. Elle s’adresse à toute personne qui configure un flux IoT Logic et ne suppose aucune connaissance en programmation.

La page s’applique aux deux endroits où vous écrivez une expression : le **Formule** champ d’un [Initialiser un Attribut](/docs/user/fr/guide/account/iot-logic/nodes/initiate-attribute-node.md) nœud, et le **champ Expression de condition (JEXL)** champ d’un [Logique](/docs/user/fr/guide/account/iot-logic/nodes/logic-node.md) nœud.

## Lorsqu’une expression ne peut pas produire de valeur

Une valeur vide bloque l’expression entière. Cela s’applique de part et d’autre d’un calcul, d’une comparaison de taille, d’un test de préfixe de texte ou d’un opérateur logique `!`, `&&`, ou `||`. Dans une formule et dans l’Analyseur de données, une valeur vide apparaît comme `null`.

La lecture d’un attribut qu’un appareil GPS n’a jamais envoyé n’est pas une erreur en soi. Ce qui s’arrête, c’est l’opérateur qui doit ensuite travailler avec la valeur vide. Une seule valeur vide bloque l’expression entière, y compris les parties qui avaient des valeurs. Une condition qui teste quatre géofences s’arrête au premier qui ne peut pas répondre, et les trois autres ne sont jamais testés. L’exception est un terme antérieur dans l’expression qui a déjà fixé le résultat.

## Ce que vous voyez lorsqu’une expression ne produit rien

Rien n’indique l’échec. Le résultat dépend du nœud qui contient l’expression :

| Où l’expression s’exécute                                            | Ce qui se passe pour ce paquet de données                                                                                         |
| -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| **Formule** champ d’un **Initialiser un Attribut** Nœud              | L’attribut n’a aucune valeur pour ce paquet, et l’Analyseur de données l’affiche comme `null`.                                    |
| **champ Expression de condition (JEXL)** champ d’un **Logique** Nœud | Les données sortent par la connexion ELSE, et le nœud enregistre son propre attribut comme une valeur vide, et non comme `false`. |

{% hint style="warning" %}
Rien ne signale l’échec. Aucune erreur n’apparaît dans le flux, aucun compteur ne change, et tous les autres attributs sont toujours calculés normalement. Le seul signe est la valeur manquante elle-même, si bien qu’un flux peut sembler sain alors qu’un attribut ne produit aucune valeur pendant des semaines.

L’enregistrement d’un flux ne prouve pas non plus qu’une formule fonctionne. La vérification effectuée lors de l’enregistrement confirme que l’expression est écrite correctement. Elle n’exécute pas l’expression sur les données de votre appareil GPS, donc une formule qui ne produit rien pour chaque paquet s’enregistre quand même sans avertissement.
{% endhint %}

## Comment chaque opérateur gère une valeur vide

Quatre opérateurs continuent toujours de fonctionner sur une valeur vide : `==`, `!=`, `=~` et `!~`. Les opérateurs `&&` et `||` continuent de fonctionner uniquement lorsque le côté lu en premier fixe la réponse. Tous les autres opérateurs s’arrêtent.

Ce tableau couvre un attribut que vous référencez par son nom, c’est-à-dire la forme que [le remplissage automatique](/docs/user/fr/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#autofill-attribute-names) insère. Quatre opérateurs se comportent différemment lorsque la valeur provient de `value()` à la place. Voir [Lecture par nom ou avec value()](#reading-by-name-or-with-value).

| Opérateur                                                         | Avec une valeur vide d’un côté ou de l’autre                                                                        |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `==`, `!=` (égal à, différent de)                                 | Renvoie un vrai oui ou non. `null == null` est `true` et `null != null` est `false`.                                |
| `=~`, `!~` (est dans une liste ou correspond à un motif de texte) | Renvoie un vrai oui ou non. Une valeur vide ne correspond jamais, donc `=~` renvoie `false` et `!~` renvoie `true`. |
| `??` (utiliser une valeur de repli)                               | Renvoie la valeur de droite. Elle remplace uniquement une valeur vide.                                              |
| `?:` (utiliser une valeur de repli)                               | Renvoie la valeur de droite. Elle remplace également `false`, pour `0`, et pour le texte vide.                      |
| `a ? b : c` (choisir entre deux valeurs)                          | Prend la `c` branche, de la même manière que pour `false`.                                                          |
| `=^`, `!^`, `=$`, `!$` (commence par, se termine par)             | L’expression ne produit rien.                                                                                       |
| `<`, `<=`, `>`, `>=` (comparaisons de taille)                     | L’expression ne produit rien.                                                                                       |
| `+`, `-`, `*`, `/`, `%` (arithmétique)                            | L’expression ne produit rien.                                                                                       |
| `&`, `\|`, `^` (opérations sur les bits)                          | L’expression ne produit rien.                                                                                       |
| `!` (non)                                                         | L’expression ne produit rien.                                                                                       |
| `&&`, `\|\|` (et, ou)                                             | L’expression ne produit rien, sauf si le côté lu en premier fixe la réponse.                                        |

Les six opérateurs de texte se divisent en deux. `=~` et `!~` tolère une valeur vide, mais `=^`, `!^`, `=$` et `!$` ne le font pas lorsque l'attribut est référencé par son nom. Une condition telle que `hardware_key !^ 'AB'` semble être un moyen sûr d'exclure un préfixe, mais elle ne produit rien sur chaque paquet sans `hardware_key`.

Le `math:` les fonctions ne produisent rien lorsqu'elles reçoivent une valeur vide, donc `math:round(engine_temp)` ne produit rien lorsque `engine_temp` est manquant. Le `util :` les fonctions sont plus tolérantes et renvoient une valeur vide à la place, donc `util:join` et `util:joinNonNull` produisent quand même un résultat lorsqu’un de leurs arguments est manquant. La concaténation de texte avec `+` n’est pas tolérante : `'Zone: ' + zone_label` ne produit rien.

## Opérateurs logiques avec une valeur vide

L’ordre compte pour les deux `&&` et `||`. Chaque opérateur lit d’abord le côté gauche et s’arrête là lorsque le côté gauche détermine déjà le résultat. Un `false` la partie gauche court-circuite `&&`, et une `true` la partie gauche court-circuite `||`.

| Expression                   | Résultat                                                                                      |
| ---------------------------- | --------------------------------------------------------------------------------------------- |
| `false && (empty)`           | `false`. Une partie gauche fausse court-circuite AND, donc la partie droite n'est jamais lue. |
| `true && (empty)`            | Ne produit rien.                                                                              |
| `(empty) && anything`        | Ne produit rien. La partie gauche est lue en premier.                                         |
| `true \|\| (empty)`          | `true`. Une partie gauche vraie court-circuite OR, donc la partie droite n'est jamais lue.    |
| `faux \|\| (vide)`           | Ne produit rien.                                                                              |
| `(vide) \|\| n'importe quoi` | Ne produit rien. La partie gauche est lue en premier.                                         |

Placer en dernier le terme qui peut être vide n’est utile que lorsque le côté gauche fixe le résultat sur ce paquet. Vous pouvez rarement garantir ce résultat ; comparez donc explicitement la valeur à la place.

## Lecture par nom ou avec value()

Quatre opérateurs donnent des résultats différents pour la même valeur manquante, selon la manière dont la formule la lit. Les opérateurs sont `=^`, `!^`, `=$` et `!$`, celles qui testent le début ou la fin d’une valeur textuelle.

| Formule                                | Résultat lorsque `conducteur_id` n’a jamais été envoyé |
| -------------------------------------- | ------------------------------------------------------ |
| `conducteur_id !^ 'AB'`                | Ne produit rien                                        |
| `value('driver_id', 0, 'all') !^ 'AB'` | `true`                                                 |

Faire référence à l’attribut par son nom est le Formulaire qui [le remplissage automatique](/docs/user/fr/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#autofill-attribute-names) insère, de sorte qu’une condition construite avec le sélecteur d’attributs emprunte le premier chemin. Rédigez la comparaison avec `value()` lorsque vous devez `!^` ou `!$` signaler `true` sur un paquet qui ne porte pas l’attribut.

Tous les autres opérateurs fonctionnent de la même manière dans les deux formes. Une comparaison de taille, des opérations arithmétiques et `!` tous ne produisent rien dans tous les cas, et `==`, `!=`, `=~` et `!~` Tous donnent de toute façon un vrai oui ou un vrai non.

La même répartition s’applique aux deux formulaires de repli. `??` et `? :` peut contenir un calcul ayant échoué lorsque la valeur provient de `value()`, et ce n'est pas possible lorsqu'il provient d'un nom :

| Formule                                               | Résultat lorsque `Compteur kilométrique` n’a jamais été envoyé |
| ----------------------------------------------------- | -------------------------------------------------------------- |
| `(Compteur kilométrique + 1) ?? 0`                    | Ne produit rien                                                |
| `(value('Compteur kilométrique', 0, 'all') + 1) ?? 0` | `0`                                                            |

Une simple `??` sur un nom fonctionne toujours, car aucun calcul n’a lieu avant cela. Seul un calcul encapsulé à l’intérieur `??` ou `? :` se comporte différemment.

## Comparer une valeur explicitement

Pour rendre sûre, dans une condition, une valeur qui peut être vide, comparez-la à `== true` ou `== false` au lieu de l’utiliser seule. Les deux `==` et `!=` donnent un vrai oui ou non pour une valeur vide, de sorte qu’un terme sans données n’arrête plus toute la condition.

Cette condition s’arrête sur n’importe quel paquet où l’un des deux attributs est manquant :

```jexl
door_open || hood_open
```

Cette condition continue de fonctionner et renvoie oui lorsque l’une ou l’autre porte est ouverte :

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

Les fonctions de zone géographique fonctionnent de la même manière, car elles renvoient une valeur vide lorsqu’un paquet ne contient pas de position. Cette condition s’arrête dès que l’une des fonctions ne peut pas répondre :

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

Cette condition teste les deux zones géographiques à chaque paquet :

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

Choisissez la comparaison qui correspond à ce qu’un paquet sans données doit être considéré comme :

* `== true` signifie « considéré comme oui ». Une valeur vide donne `false`; donc un paquet sans données ne correspond pas.
* `== false` signifie « considéré comme non ». Une valeur vide donne `false`; donc un paquet sans données ne correspond pas.
* `!= true` signifie « pas connu comme étant oui ». Une valeur vide donne `true`; donc un paquet sans données correspond.

{% hint style="warning" %}
N’utilisez pas `!` sur une valeur qui peut être vide. `!inZone géographique(35229)` ne produit rien lorsque la position est inconnue, donc il ne peut pas détecter un appareil en dehors de la Zone géographique. Écrivez `inZone géographique(35229) == false` pour « connu comme étant à l’extérieur », ou `inZone géographique(35229) != true` pour « non connu comme étant à l’intérieur ».
{% endhint %}

## D’où proviennent les valeurs vides

Un attribut dans une formule prend la valeur vide dans les cas suivants :

* L’attribut n’a jamais été envoyé pour ce dispositif GPS.
* Le paquet actuel ne contient pas l’attribut, même si un paquet précédent le contenait.
* La position d’historique que vous avez demandée avec `value()` n’existe pas encore, car l’appareil a envoyé moins de paquets que la position ne l’exige.
* n’a rien envoyé pendant plus de 30 jours, donc Navixy a supprimé son historique stocké. Voir [Syntaxe complète](/docs/user/fr/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#full-syntax).
* `inGeofence()`, `enterGeofence()`, ou `leaveGeofence()` ne peut pas répondre, car le paquet ne contient aucune coordonnée ou la zone géographique n’existe plus dans le compte. Voir [Quand une fonction de zone géographique ne donne aucune réponse](/docs/user/fr/guide/account/iot-logic/nodes/geofence-functions.md#when-a-geofence-function-gives-no-answer).
* `geofenceName()` n’a aucun nom à renvoyer. Voir [Ce que vous obtenez en retour](/docs/user/fr/guide/account/iot-logic/nodes/geofence-functions.md#what-you-get-back).

Toutes ces causes se présentent de la même manière dans une formule. Une formule qui doit continuer à fonctionner doit gérer la valeur vide plutôt que la cause.

## Formules qui doivent toujours produire une valeur

Protégez le calcul avec `!= null`, et placez la garde en premier. La garde utilise `!=`, ce qui donne un vrai oui ou non pour une valeur vide, de sorte que le garde lui-même ne s'arrête jamais :

```jexl
value('Compteur kilométrique', 0, 'all') != null && value('Compteur kilométrique', 0, 'all') > 100
```

L’ordre est ce qui permet au garde de fonctionner. Si vous inversez les termes, la comparaison s’exécute avant le garde, et l’ensemble de la condition ne produit rien.

Pour substituer une valeur de repli à la place, utilisez `??`. Il renvoie la partie droite uniquement lorsque la partie gauche est vide :

```jexl
can_speed ?? 0
```

`??` substitue une valeur manquante, pas un calcul qui a échoué. `(can_speed * 1.1) ?? 0` ne produit rien lorsque `can_speed` est manquant, car la multiplication s’arrête avant `??` qu’il ne soit atteint. Placez `??` autour de l’attribut plutôt qu’autour du calcul :

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

{% hint style="warning" %}
`?:` et `??` se ressemblent et se comportent différemment. `??` ne remplace la partie de droite qu’en cas de valeur vide. `?:` la remplace pour une valeur vide et aussi pour `false`, pour `0`, et pour le texte vide. La formule `Contact ?: true` rapporte donc `true` lorsque Contact est réellement désactivé. Utilisez `??` lorsque vous voulez dire « si la valeur est manquante ».
{% endhint %}

Vous pouvez également conditionner le calcul depuis l'extérieur de la formule. Placez un **Logique** Nœud avant le **Initialiser un Attribut** Nœud, puis vérifiez la présence des attributs dans sa condition. Connectez la branche THEN au Nœud de calcul, afin qu'il reçoive uniquement les paquets qui contiennent les valeurs dont il a besoin.

Connectez la branche ELSE à un **Point de sortie** Nœud également. Une branche qui se termine sans en avoir un supprime chaque paquet qui y parvient, de sorte que les paquets qui n'ont pas passé le test de présence ne quittent jamais le flux.

Lorsque l'absence de valeur vaut mieux qu'une valeur incorrecte, un attribut sans valeur est le résultat correct. Ajoutez une valeur de repli uniquement lorsqu'un système plus en aval dans le flux a besoin d'une valeur pour chaque paquet.

## Vérifiez si une expression ne produit rien

Travaillez à partir de ce que vous pouvez voir dans [Analyseur de données](/docs/user/fr/guide/account/iot-logic/data-stream-analyzer.md):

1. Sélectionnez le flux, puis l'appareil GPS et l'attribut calculé.
2. Désactivez le **Exclure les valeurs nulles** interrupteur. Un calcul échoué apparaît comme une `null` valeur. L'interrupteur masque ces valeurs lorsqu'il est activé.
3. Augmentez la profondeur si le paquet que vous recherchez est plus ancien que les valeurs affichées à l'écran.
4. Comparez l'attribut avec les attributs que sa formule lit. Un paquet où les entrées de la formule ont des valeurs et où l'attribut calculé est `null` pointe vers la formule.
5. Vérifiez chaque opérateur de la formule par rapport à [Comment chaque opérateur gère une valeur vide](#how-each-operator-handles-an-empty-value).
6. Réécrivez chaque partie qui pourrait être vide. Utilisez `== true`, `== false`, ou une `??` solution de repli.

{% hint style="warning" %}
Lorsque **Exclure les valeurs nulles** est activé, la dernière valeur produite par la formule reste affichée à l’écran avec son horodatage plus ancien. La lecture semble actuelle, mais elle appartient à un paquet antérieur. Désactivez le bouton bascule avant de juger si IoT Logic calcule encore un attribut.
{% endhint %}

## Foire aux questions

#### Une valeur vide est-elle la même chose que `false`?

Non. Une condition qui est réellement `false` stocke `false`, et une condition qui n'a pas pu être évaluée stocke une valeur vide. Les deux envoient les données via la connexion ELSE d'un **Logique** nœud, donc la branche seule ne vous dit pas ce qui s'est passé. Une expression ultérieure qui teste l'attribut avec `my_flag == false` ne correspond qu'au premier cas.

#### Pourquoi un appareil GPS a-t-il cessé de correspondre à une condition qui fonctionne encore pour les autres ?

Les appareils de modèles différents n'envoient pas tous les mêmes attributs, et un appareil peut cesser de signaler un attribut que les autres envoient encore. Une condition qui lit cet attribut sans comparaison ne produit alors aucun résultat pour cet appareil uniquement. Comparez chaque terme explicitement avec `== true` ou `== false`.

## Voir aussi

* [Expressions et syntaxe de Logique](/docs/user/fr/guide/account/iot-logic/nodes/logic-node/logic-node-expressions-and-syntax.md#missing-values-and-null-routing) quelle branche un Nœud Logic prend et ce qu'il y stocke.
* [Fonctions de zone géographique](/docs/user/fr/guide/account/iot-logic/nodes/geofence-functions.md) pour les cas où une fonction de Zone géographique ne peut pas répondre.
* [Gestion des attributs](/docs/user/fr/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#expression-language) pour la `value()` fonction et les deux options de syntaxe.
* [Exemples de calcul](/docs/user/fr/guide/account/iot-logic/nodes/initiate-attribute-node/calculation-examples.md) pour des exemples de formule.


---

# 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/fr/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.
