> 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 ada, dan pola perbandingan mana yang mencegahnya.

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

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

## Ketika sebuah ekspresi tidak dapat menghasilkan nilai

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

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

## Apa yang Anda lihat ketika 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 pada sebuah **Inisiasi Atribut** node         | Atribut tersebut tidak memiliki nilai untuk paket itu, dan Penganalisis Data menampilkannya sebagai `null`.          |
| **Ekspresi kondisi (JEXL)** kolom pada 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 dalam aliran, tidak ada penghitung yang berubah, dan setiap atribut lain tetap dihitung secara normal. Satu-satunya tanda adalah nilai yang hilang itu sendiri, sehingga sebuah aliran dapat tampak sehat sementara satu atribut tidak menghasilkan nilai selama berminggu-minggu.

Menyimpan sebuah aliran juga tidak membuktikan bahwa sebuah formula berfungsi. Pemeriksaan yang berjalan 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. Semua operator lainnya berhenti.

Tabel ini mencakup atribut yang Anda referensikan dengan nama, yang merupakan bentuk yang [pengisian otomatis](/docs/user/id/guide/account/iot-logic/nodes/initiate-attribute-node/managing-attributes.md#autofill-attribute-names) menyisipkan. 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 `c` cabang, sama seperti untuk `false`.                                                                                               |
| `=^`, `!^`, `=$`, `!$` (diawali 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 membagi menjadi dua. `=~` dan `!~` tetap berfungsi pada nilai kosong, tetapi `=^`, `!^`, `=$`, dan `!$` tidak demikian saat atribut direferensikan dengan nama. Kondisi seperti `hardware_key !^ 'AB'` terlihat seperti cara aman untuk mengecualikan awalan, tetapi tidak menghasilkan apa pun pada setiap paket tanpa `hardware_key`.

Sebuah `matematika:` fungsi tidak menghasilkan apa pun ketika menerima nilai kosong, sehingga `math:round(engine_temp)` tidak menghasilkan apa pun 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 argumen mereka tidak ada. Menggabungkan teks dengan `+` tidak toleran: `'Zona: ' + zone_label` tidak menghasilkan apa pun.

## Operator logika dengan nilai kosong

Urutan penting untuk keduanya `&&` dan `||`Sebuah `false` sisi kiri menentukan hasil `&&`, dan sebuah `true` sisi kiri menentukan hasil `||`.

| Ekspresi                | Hasil                                                                                            |
| ----------------------- | ------------------------------------------------------------------------------------------------ |
| `false && (kosong)`     | `false`. Sisi kiri bernilai false menentukan hasil 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 yang bernilai benar menetapkan 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 bagian yang mungkin kosong di urutan terakhir hanya membantu ketika sisi kiri menetapkan 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 hilang yang sama, bergantung pada bagaimana rumus membacanya. Operatornya adalah `=^`, `!^`, `=$` dan `!$`, yang menguji awal atau akhir dari nilai teks.

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

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

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

Pembagian yang sama berlaku untuk kedua formulir cadangan. `??` dan `? :` dapat memuat hasil perhitungan yang gagal ketika nilainya berasal dari `value()`, dan tidak bisa 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`                                        |

Perbandingan biasa `??` pada sebuah nama tetap berfungsi, karena tidak ada perhitungan yang terjadi sebelum itu. Hanya perhitungan yang dibungkus di dalam `??` atau `? :` berperilaku berbeda.

## Bandingkan nilai secara eksplisit

Untuk membuat nilai yang mungkin kosong aman dalam sebuah kondisi, bandingkan nilainya dengan `== true` atau `== false` daripada menggunakannya sendiri. Keduanya `==` dan `!=` memberikan jawaban ya atau tidak yang benar 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 tidak ada:

```jexl
door_open || hood_open
```

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

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

Fungsi Perimeter berperilaku sama, karena fungsi-fungsi itu mengembalikan nilai kosong ketika 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 /* Gudang Austin */) == true || leaveGeofence(85269 /* Lokasi konstruksi 1 */) == true
```

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

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

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

## Sumber nilai kosong

Sebuah atribut dalam formula akan menghasilkan nilai kosong dalam kasus-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 diperlukan 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 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 Anda peroleh](/docs/user/id/guide/account/iot-logic/nodes/geofence-functions.md#what-you-get-back).

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

## Formula yang harus selalu menghasilkan nilai

Amankan perhitungan dengan `!= null`, dan tempatkan pengaman di depan. Pengaman menggunakan `!=`, yang memberikan jawaban ya atau tidak yang benar untuk nilai kosong, sehingga pengaman itu sendiri tidak pernah berhenti:

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

Urutan itulah yang membuat pengaman bekerja. Jika Anda membalik istilahnya, perbandingan dijalankan sebelum pengaman, dan seluruh kondisi tidak menghasilkan apa pun.

Untuk menggantinya dengan nilai cadangan, gunakan `??`. Operator ini mengembalikan sisi kanan hanya ketika sisi kiri kosong:

```jexl
can_speed ?? 0
```

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

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

{% hint style="warning" %}
`?:` dan `??` tampak serupa dan berperilaku berbeda. `??` menggantikan sisi kanan hanya untuk nilai kosong. `?:` menggantinya untuk nilai kosong dan juga untuk `false`, untuk `0`, dan untuk teks kosong. Rumus `Pengapian ?: true` karena itu melaporkan `true` saat Pengapian benar-benar mati. Gunakan `??` ketika Anda bermaksud "jika nilainya hilang".
{% endhint %}

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

Sambungkan jalur ELSE ke sebuah **Titik Akhir Output** node juga. Cabang yang berakhir tanpa node demikian akan membuang setiap paket yang mencapainya, sehingga paket yang gagal lulus uji keberadaan tidak pernah keluar dari aliran.

Ketika tanpa nilai lebih baik daripada nilai yang salah, atribut tanpa nilai adalah hasil yang benar. Tambahkan nilai cadangan hanya ketika sistem yang berada lebih jauh di aliran memerlukan nilai pada setiap paket.

## Periksa apakah sebuah ekspresi tidak menghasilkan apa pun

Mulailah 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 `null` nilai. Sakelar menyembunyikan nilai tersebut saat aktif.
3. Tingkatkan kedalaman jika paket yang Anda cari lebih lama daripada nilai yang ditampilkan di layar.
4. Bandingkan atribut tersebut dengan atribut yang dibaca oleh rumusnya. Paket tempat input rumus memiliki nilai dan atribut yang dihitung adalah `null` menunjuk ke rumus.
5. Periksa setiap operator dalam rumus 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 `??` nilai cadangan.

{% hint style="warning" %}
Saat **Kecualikan null** saat aktif, nilai terakhir yang dihasilkan rumus tetap tampil di layar dengan stempel waktu lamanya sendiri. Pembacaan tampak terkini, tetapi itu milik paket yang lebih awal. Nonaktifkan sakelar sebelum Anda menilai apakah IoT Logic masih menghitung 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 itu sendiri tidak memberi tahu Anda mana yang terjadi. Ekspresi berikutnya yang menguji atribut dengan `my_flag == false` hanya cocok dengan kasus pertama.

#### Mengapa satu perangkat GPS berhenti cocok dengan suatu kondisi yang masih berfungsi untuk yang lain?

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

## Lihat juga

* [Ekspresi dan sintaks Logika IF/THEN](/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 ketika fungsi Perimeter tidak dapat memberikan jawaban.
* [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 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/id/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.
