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

# Nilai yang hilang dalam ekspresi

Pahami mengapa rumus atau kondisi IoT Logic tidak menghasilkan nilai ketika nilai yang dibutuhkannya tidak tersedia, dan pola perbandingan mana yang mencegahnya.

Formula dan kondisi di IoT Logic bekerja pada nilai yang dikirimkan perangkat GPS. Saat nilai yang dibutuhkan sebuah formula tidak ada, sebagian besar operator tidak dapat menghasilkan hasil, dan formula sama sekali tidak menghasilkan apa pun: tidak `false`, dan bukan nol. Halaman ini menjelaskan kapan nilai hilang, seperti apa kegagalannya, dan cara menulis formula dan kondisi yang tetap bekerja. Halaman ini ditujukan bagi siapa pun yang mengonfigurasi aliran IoT Logic, dan mengasumsikan tidak ada latar belakang pemrograman.

Halaman ini berlaku untuk kedua tempat Anda menulis ekspresi: **Rumus** kolom sebuah [Inisiasi Atribut](/docs/user/id/guide/account/iot-logic/nodes/initiate-attribute-node.md) node, dan **bidang ekspresi kondisi (JEXL)** kolom sebuah [Logika](/docs/user/id/guide/account/iot-logic/nodes/logic-node.md) node.

## Saat sebuah ekspresi tidak dapat menghasilkan nilai

Nilai kosong menghentikan seluruh ekspresi. Hal ini berlaku di kedua sisi perhitungan, perbandingan ukuran, pengujian awalan teks, atau operator logika `!`, `&&`, atau `||`. Di dalam formula dan di Penganalisis Data, nilai kosong muncul sebagai `null`.

Membaca atribut yang belum pernah dikirim perangkat GPS bukanlah kesalahan itu sendiri. Yang berhenti adalah operator yang kemudian harus bekerja dengan nilai kosong. Satu nilai kosong menghentikan seluruh ekspresi, termasuk bagian yang sudah memiliki nilai. Kondisi yang menguji empat geofence berhenti pada geofence pertama yang tidak dapat memberikan jawaban, dan tiga lainnya tidak pernah diuji. Pengecualiannya adalah suatu istilah di bagian awal ekspresi yang sudah lebih dulu menentukan hasil.

## Apa yang Anda lihat saat sebuah ekspresi tidak menghasilkan apa pun

Tidak ada yang menandai kegagalan. Hasilnya bergantung pada node mana yang memuat ekspresi:

| Tempat ekspresi dijalankan                                      | Apa yang terjadi pada paket data tersebut                                                                            |
| --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| **Rumus** kolom sebuah **Inisiasi Atribut** node                | Atribut tersebut tidak memiliki nilai untuk paket data itu, dan Penganalisis Data menampilkannya sebagai `null`.     |
| **bidang ekspresi kondisi (JEXL)** kolom sebuah **Logika** node | Data keluar melalui koneksi ELSE, dan node menyimpan atributnya sendiri sebagai nilai kosong, bukan sebagai `false`. |

{% hint style="warning" %}
Tidak ada yang melaporkan kegagalan. Tidak ada kesalahan yang muncul di aliran, tidak ada penghitung yang berubah, dan setiap atribut lainnya tetap dihitung secara normal. Satu-satunya tanda adalah nilai yang hilang itu sendiri, sehingga suatu aliran dapat terlihat sehat sementara satu atribut tidak menghasilkan nilai selama berminggu-minggu.

Menyimpan aliran juga tidak membuktikan bahwa sebuah formula berfungsi. Pemeriksaan yang dijalankan saat Anda menyimpan hanya memastikan bahwa ekspresi ditulis dengan benar. Pemeriksaan itu tidak menjalankan ekspresi terhadap data perangkat GPS Anda, sehingga formula yang tidak menghasilkan apa pun pada setiap paket tetap tersimpan tanpa peringatan.
{% endhint %}

## Cara setiap operator menangani nilai kosong

Empat operator selalu tetap bekerja pada nilai kosong: `==`, `!=`, `=~`, dan `!~`Operator `&&` dan `||` tetap bekerja hanya ketika sisi yang dibaca terlebih dahulu sudah menentukan jawabannya. Setiap operator lainnya berhenti.

Tabel ini mencakup atribut yang Anda rujuk berdasarkan nama, yaitu bentuk yang [pengisian otomatis](/docs/user/id/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#autofill-attribute-names) disisipkan. Empat operator berperilaku berbeda ketika nilai berasal dari `value()` sebagai gantinya. Lihat [Membaca berdasarkan nama atau dengan value()](#reading-by-name-or-with-value).

| Operator                                                   | Dengan nilai kosong di kedua sisi                                                                                                               |
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `==`, `!=` (sama dengan, tidak sama dengan)                | Memberikan jawaban ya atau tidak yang sebenarnya. `null == null` adalah `true`, dan `null != null` adalah `false`.                              |
| `=~`, `!~` (ada dalam daftar, atau cocok dengan pola teks) | Memberikan jawaban ya atau tidak yang sebenarnya. Nilai kosong tidak pernah cocok, jadi `=~` menghasilkan `false` dan `!~` menghasilkan `true`. |
| `??` (gunakan nilai cadangan)                              | Memberikan nilai di sebelah kanan. Ini hanya menggantikan nilai kosong.                                                                         |
| `?:` (gunakan nilai cadangan)                              | Memberikan nilai di sebelah kanan. Ini juga menggantikan `false`, untuk `0`, dan untuk teks kosong.                                             |
| `a ? b : c` (memilih di antara dua nilai)                  | Mengambil cabang `c` , sama seperti pada `false`.                                                                                               |
| `=^`, `!^`, `=$`, `!$` (dimulai dengan, diakhiri dengan)   | Ekspresi tidak menghasilkan apa pun.                                                                                                            |
| `<`, `<=`, `>`, `>=` (perbandingan ukuran)                 | Ekspresi tidak menghasilkan apa pun.                                                                                                            |
| `+`, `-`, `*`, `/`, `%` (aritmetika)                       | Ekspresi tidak menghasilkan apa pun.                                                                                                            |
| `&`, `\|`, `^` (operasi bit)                               | Ekspresi tidak menghasilkan apa pun.                                                                                                            |
| `!` (tidak)                                                | Ekspresi tidak menghasilkan apa pun.                                                                                                            |
| `&&`, `\|\|` (dan, atau)                                   | Ekspresi tidak menghasilkan apa pun, kecuali jika sisi yang dibaca terlebih dahulu sudah menentukan jawabannya.                                 |

Enam operator teks terbagi menjadi dua. `=~` dan `!~` tetap berlaku saat nilai kosong, tetapi `=^`, `!^`, `=$`, dan `!$` tidak demikian ketika atribut direferensikan berdasarkan nama. Suatu kondisi seperti `hardware_key !^ 'AB'` tampak seperti cara aman untuk mengecualikan awalan, tetapi tidak menghasilkan apa-apa pada setiap paket tanpa `hardware_key`.

Blok `matematika:` fungsi tidak menghasilkan apa-apa saat menerima nilai kosong, jadi `math:round(engine_temp)` tidak menghasilkan apa-apa ketika `engine_temp` tidak ada. The `util:` fungsi lebih toleran dan mengembalikan nilai kosong sebagai gantinya, sehingga `util:join` dan `util:joinNonNull` tetap menghasilkan hasil ketika salah satu argumennya hilang. Menggabungkan teks dengan `+` tidak toleran: `'Zona: ' + zone_label` tidak menghasilkan apa pun.

## Operator logika dengan nilai kosong

Urutan penting untuk keduanya `&&` dan `||`. Setiap operator membaca sisi kiri terlebih dahulu dan berhenti di sana ketika sisi kiri sudah menentukan hasil. Sebuah `false` sisi kiri menentukan `&&`, dan sebuah `true` sisi kiri menentukan `||`.

| Ekspresi                | Hasil                                                                             |
| ----------------------- | --------------------------------------------------------------------------------- |
| `false && (kosong)`     | `false`. Sisi kiri false menentukan AND, sehingga sisi kanan tidak pernah dibaca. |
| `true \|\| (kosong)`    | Tidak menghasilkan apa pun.                                                       |
| `(kosong) && apa pun`   | Tidak menghasilkan apa pun. Sisi kiri dibaca terlebih dahulu.                     |
| `true \|\| (kosong)`    | `true`. Sisi kiri true menentukan OR, sehingga sisi kanan tidak pernah dibaca.    |
| `false \|\| (kosong)`   | Tidak menghasilkan apa pun.                                                       |
| `(kosong) \|\| apa pun` | Tidak menghasilkan apa pun. Sisi kiri dibaca terlebih dahulu.                     |

Menempatkan istilah yang mungkin kosong di urutan terakhir hanya membantu ketika sisi kiri menentukan hasil pada paket tersebut. Anda jarang dapat menjamin hasil itu, jadi bandingkan nilainya secara eksplisit saja.

## Membaca berdasarkan nama atau dengan value()

Empat operator memberikan hasil yang berbeda untuk nilai yang sama yang hilang, tergantung pada cara rumus membacanya. Operator-operatornya adalah `=^`, `!^`, `=$` dan `!$`, yang menguji awal atau akhir dari sebuah nilai teks.

| Rumus                                  | Hasil saat `supir_id` tidak pernah dikirim |
| -------------------------------------- | ------------------------------------------ |
| `supir_id !^ 'AB'`                     | Tidak menghasilkan apa pun                 |
| `value('driver_id', 0, 'all') !^ 'AB'` | `true`                                     |

Merujuk atribut berdasarkan nama adalah bentuk yang [pengisian otomatis](/docs/user/id/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#autofill-attribute-names) menyisipkan, sehingga kondisi yang dibuat dengan pemilih atribut mengambil jalur pertama. Tulis perbandingan dengan `value()` saat Anda perlu `!^` atau `!$` melaporkan `true` pada paket yang tidak memiliki atribut tersebut.

Semua operator lainnya berperilaku sama dalam kedua bentuk. Perbandingan ukuran, aritmetika, dan `!` semuanya tidak menghasilkan apa pun dengan cara apa pun, dan `==`, `!=`, `=~` dan `!~` semuanya memberikan jawaban ya atau tidak yang jelas, apa pun pilihannya.

Pemisahan yang sama berlaku untuk kedua bentuk cadangan. `??` dan `? :` dapat berisi perhitungan yang gagal ketika nilainya berasal dari `value()`, dan tidak dapat ketika berasal dari sebuah nama:

| Rumus                                    | Hasil saat `odometer` tidak pernah dikirim |
| ---------------------------------------- | ------------------------------------------ |
| `(odometer + 1) ?? 0`                    | Tidak menghasilkan apa pun                 |
| `(value('odometer', 0, 'all') + 1) ?? 0` | `0`                                        |

Ekspresi biasa `??` pada sebuah nama masih berfungsi, karena tidak ada perhitungan yang terjadi sebelumnya. Hanya perhitungan yang dibungkus di dalam `??` atau `? :` yang berperilaku berbeda.

## Bandingkan nilai secara eksplisit

Untuk membuat nilai yang mungkin kosong aman dalam suatu kondisi, bandingkan nilai itu dengan `== true` atau `== false` alih-alih menggunakannya sendiri. Keduanya `==` dan `!=` memberikan hasil ya atau tidak yang nyata untuk nilai kosong, sehingga satu istilah yang tidak memiliki data tidak lagi menghentikan seluruh kondisi.

Kondisi ini berhenti pada paket apa pun ketika salah satu dari dua atribut hilang:

```jexl
door_open || hood_open
```

Kondisi ini tetap bekerja, dan melaporkan ya ketika salah satu pintu terbuka:

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

Fungsi Perimeter berperilaku dengan cara yang sama, karena mengembalikan nilai kosong ketika sebuah paket tidak membawa posisi. Kondisi ini berhenti segera setelah salah satu fungsi tidak dapat menjawab:

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

Kondisi ini menguji kedua Perimeter pada setiap paket:

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

Pilih perbandingan yang sesuai dengan bagaimana paket tanpa data harus dihitung:

* `== true` berarti "diketahui ya". Nilai kosong menghasilkan `false`, sehingga paket tanpa data tidak cocok.
* `== false` berarti "diketahui tidak". Nilai kosong menghasilkan `false`, sehingga paket tanpa data tidak cocok.
* `!= true` berarti "tidak diketahui ya". Nilai kosong menghasilkan `true`, sehingga paket tanpa data cocok.

{% hint style="warning" %}
Jangan gunakan `!` pada nilai yang mungkin kosong. `!inGeofence(35229)` tidak menghasilkan apa pun ketika posisi tidak diketahui, sehingga tidak dapat mendeteksi perangkat di luar Perimeter. Tulis `inGeofence(35229) == false` untuk "diketahui berada di luar", atau `inGeofence(35229) != true` untuk "tidak diketahui berada di dalam".
{% endhint %}

## Dari mana nilai kosong berasal

Atribut dalam formula berubah menjadi nilai kosong dalam kasus berikut:

* Atribut tersebut belum pernah dikirim untuk perangkat GPS itu.
* Paket saat ini tidak membawa atribut tersebut, meskipun paket sebelumnya membawanya.
* Posisi riwayat yang Anda minta dengan `value()` belum ada, karena perangkat telah mengirim lebih sedikit paket daripada yang disyaratkan oleh posisi tersebut.
* Perangkat tidak mengirim apa pun selama lebih dari 30 hari, sehingga Navixy menghapus riwayat yang tersimpan. Lihat [Sintaks lengkap](/docs/user/id/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#full-syntax).
* `inGeofence()`, `enterGeofence()`, atau `leaveGeofence()` tidak dapat menjawab, karena paket tidak membawa koordinat atau Perimeter tersebut tidak lagi ada di akun. Lihat [Saat fungsi perimeter tidak memberikan jawaban](/docs/user/id/guide/account/iot-logic/nodes/geofence-functions.md#when-a-geofence-function-gives-no-answer).
* `geofenceName()` tidak memiliki nama untuk dikembalikan. Lihat [Apa yang dikembalikan](/docs/user/id/guide/account/iot-logic/nodes/geofence-functions.md#what-you-get-back).

Semua penyebab ini tampak sama dalam formula. Formula yang harus tetap berfungsi harus menangani nilai kosong, bukan penyebabnya.

## Formula yang harus selalu menghasilkan nilai

Lindungi perhitungan dengan `!= null`, dan letakkan pelindung di depan. Pelindung menggunakan `!=`, yang memberikan hasil ya atau tidak yang nyata untuk nilai kosong, sehingga pelindung itu sendiri tidak pernah berhenti:

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

Urutanlah yang membuat pelindung bekerja. Jika Anda membalik istilah-istilahnya, perbandingan berjalan sebelum pelindung, dan seluruh kondisi tidak menghasilkan apa pun.

Untuk menggantikan nilai cadangan sebagai gantinya, gunakan `??`. Nilai di sisi kanan hanya dikembalikan ketika sisi kiri kosong:

```jexl
can_speed ?? 0
```

`??` menggantikan nilai yang hilang, bukan perhitungan yang gagal. `(can_speed * 1.1) ?? 0` tidak menghasilkan apa-apa ketika `can_speed` hilang, karena perkalian berhenti sebelum `??` tercapai. Letakkan `??` di sekitar atribut, bukan di sekitar perhitungan:

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

{% hint style="warning" %}
`?:` dan `??` tampak serupa dan berperilaku berbeda. `??` menggantikan sisi kanan hanya untuk nilai kosong. `?:` menggantikan itu untuk nilai kosong dan juga untuk `false`, untuk `0`, dan untuk teks kosong. Formula `pengapian ?: true` karena itu menghasilkan laporan `true` saat pengapian benar-benar mati. Gunakan `??` saat yang Anda maksud adalah "jika nilai tidak ada".
{% endhint %}

Anda juga dapat membatasi perhitungan dari luar formula. Letakkan sebuah **Logika** node sebelum **Inisiasi Atribut** node, dan uji atribut untuk keberadaan dalam kondisinya. Hubungkan jalur THEN ke node penghitungan, sehingga node tersebut hanya menerima paket yang membawa nilai yang dibutuhkannya.

Hubungkan jalur ELSE ke sebuah **Titik Akhir Output** node juga. Cabang yang berakhir tanpa node tersebut akan membuang setiap paket yang mencapainya, sehingga paket yang gagal dalam uji keberadaan tidak pernah meninggalkan aliran.

Saat tidak ada nilai lebih baik daripada nilai yang salah, atribut tanpa nilai adalah hasil yang benar. Tambahkan nilai cadangan hanya ketika sistem lebih jauh di aliran membutuhkan nilai pada setiap paket.

## Periksa apakah sebuah ekspresi tidak menghasilkan apa pun

Bekerjalah dari apa yang dapat Anda lihat di [Penganalisis Data](/docs/user/id/guide/account/iot-logic/data-stream-analyzer.md):

1. Pilih aliran, lalu perangkat GPS dan atribut yang dihitung.
2. Nonaktifkan **Kecualikan null** sakelar. Perhitungan yang gagal muncul sebagai sebuah `null` nilai. Sakelar tersebut menyembunyikan nilai-nilai itu saat diaktifkan.
3. Tingkatkan kedalaman jika paket yang Anda cari lebih lama daripada nilai yang ditampilkan di layar.
4. Bandingkan atribut tersebut dengan atribut-atribut yang dibaca oleh rumusnya. Paket yang masukan rumusnya memiliki nilai dan atribut yang dihitung adalah `null` menunjuk ke formula.
5. Periksa setiap operator dalam formula terhadap [Cara setiap operator menangani nilai kosong](#how-each-operator-handles-an-empty-value).
6. Tulis ulang setiap bagian yang mungkin kosong. Gunakan `== true`, `== false`, atau sebuah `??` cadangan.

{% hint style="warning" %}
Saat **Kecualikan null** aktif, nilai terakhir yang dihasilkan formula tetap tampil di layar dengan stempel waktunya yang lebih lama. Pembacaan tampak terkini, tetapi berasal dari paket sebelumnya. Nonaktifkan sakelar sebelum Anda menilai apakah IoT Logic masih menghitung sebuah atribut.
{% endhint %}

## Pertanyaan yang sering diajukan

#### Apakah nilai kosong sama dengan `false`?

Tidak. Kondisi yang benar-benar `false` menyimpan `false`, dan kondisi yang tidak dapat dievaluasi menyimpan nilai kosong. Keduanya mengirim data melalui koneksi ELSE dari sebuah **Logika** node, sehingga cabang saja tidak memberi tahu Anda mana yang terjadi. Ekspresi berikutnya yang menguji atribut dengan `my_flag == false` hanya cocok untuk kasus pertama.

#### Mengapa satu perangkat GPS berhenti memenuhi kondisi yang masih berfungsi untuk perangkat lainnya?

Perangkat dengan model berbeda tidak semuanya mengirim atribut yang sama, dan satu perangkat dapat berhenti melaporkan atribut yang masih dikirim oleh perangkat lain. Kondisi yang membaca atribut tersebut tanpa perbandingan kemudian tidak menghasilkan apa-apa hanya untuk perangkat itu. Bandingkan setiap istilah secara eksplisit dengan `== true` atau `== false`.

## Lihat juga

* [Ekspresi dan sintaks Logika](/docs/user/id/guide/account/iot-logic/nodes/logic-node/logic-node-expressions-and-syntax.md#missing-values-and-null-routing) cabang mana yang diambil oleh node Logic dan apa yang disimpannya.
* [Fungsi Perimeter](/docs/user/id/guide/account/iot-logic/nodes/geofence-functions.md) untuk kasus saat fungsi Perimeter tidak dapat menjawab.
* [Mengelola atribut](/docs/user/id/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#expression-language) untuk `value()` fungsi dan dua opsi sintaks.
* [Contoh perhitungan](/docs/user/id/guide/account/iot-logic/nodes/initiate-attribute-node/calculation-examples.md) untuk contoh rumus.


---

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