> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flova.ir/llms.txt
> Use this file to discover all available pages before exploring further.

# Datastreamها

> قرارداد نام، نوع، جهت و رفتار داده بین دستگاه و فلووا.

Datastream مرز مشترک بین سخت‌افزار و محصول شماست. سنسور، کلید، خروجی، وضعیت و
فرمان همگی از همین مسیر عبور می‌کنند. اگر این قرارداد شفاف باشد، همان داده را
می‌توان در firmware گزارش کرد، در automation شرط گذاشت، در dashboard نمایش داد
و با FlovaQL پرس‌وجو کرد.

## کلید و عنوان

`key` نام فنی است و باید با حروف انگلیسی شروع شود و فقط حروف، عدد و underscore
داشته باشد. این کلید را بعداً بی‌دلیل عوض نکنید؛ queryها و automationها به آن
وابسته‌اند. `name` یا عنوان نمایشی می‌تواند توضیحی و فارسی باشد.

```text theme={"system"}
key: temperature
name: دمای محفظه
unit: °C
```

## نوع و حالت دسترسی

فلووا در firmware رسمی سه نوع پایهٔ `boolean`، `double` و `string` دارد. در
Device Type، حالت دسترسی را نیز تعیین می‌کنید:

| حالت         | معنی                                                        |
| ------------ | ----------------------------------------------------------- |
| `read_only`  | دستگاه گزارش می‌دهد؛ کاربر یا automation نباید در آن بنویسد |
| `write_only` | مقدار برای فرمان یا ورودی است و خواندن معمول ندارد          |
| `read_write` | هم وضعیت گزارش می‌شود و هم فرمان پذیرفته می‌شود             |

رفتار کانال می‌تواند `telemetry`، `state`، `command` یا `event` باشد. از
`telemetry` برای اندازه‌گیری‌های پیوسته، از `state` برای وضعیت قابل‌مشاهده، از
`command` برای درخواست عمل و از `event` برای رخدادهای لحظه‌ای استفاده کنید.

## `write` و `report`

در SDK، `write(value)` یک تغییر درخواستی است و از handler مربوط به سخت‌افزار
عبور می‌کند. `report(value)` می‌گوید دستگاه چنین مقداری را مشاهده کرده است و
handler فرمان را اجرا نمی‌کند. این تفاوت برای جلوگیری از حلقهٔ ناخواسته مهم
است: سنسور باید report کند، اما رله باید فرمان را از مسیر write بگیرد.

```cpp theme={"system"}
auto temperature = device.datastream<float>("temperature");
auto relay = device.datastream<bool>("relay");

relay.onWrite(setRelay);
relay.write(true);                 // فرمان محلی
temperature.report(readSensor());  // مشاهدهٔ سنسور
bool current = relay.value();      // cache محلی، بدون درخواست شبکه
```

مقدار ردشده نباید به‌عنوان وضعیت موفق ذخیره یا منتشر شود. برای رفتار قطع شبکه
نیز policy مناسب انتخاب کنید؛ مثلاً `KeepLatest` برای actuatorهایی که آخرین
فرمان معتبر را بعد از reconnect می‌خواهند.

## نکتهٔ طراحی

هر چیزی را datastream نکنید. یک مقدار فقط وقتی باید کانال مستقل داشته باشد که
قرار است در محصول دیده شود، به فرمان تبدیل شود، در automation استفاده شود یا
تاریخچهٔ آن اهمیت داشته باشد. کانال‌های داخلی و موقت را در برنامهٔ خودتان نگه
دارید.
