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

# Lesson 4 — Store Readings

> Persist device data to the product database and read it back.

**Goal:** write a reading to a database table from firmware, then show it on the
dashboard.

## 1. Create a table

In your product's database, create a schema and a table — say `readings` with a
`temperature` column. (You can also do this via the
[Database API](/api/database).)

## 2. Insert from firmware

Use `insertDatainDatabase`, building the row with a lambda:

```cpp theme={null}
device.insertDatainDatabase(productId, deviceId, "readings", [](JsonObject &row) {
  row["temperature"] = readTemperature();
  row["humidity"]    = readHumidity();
});
```

Need the result? Use the `…WithResponse` variant:

```cpp theme={null}
DynamicJsonDocument res =
  device.insertDatainDatabaseWithResponse(productId, deviceId, "readings",
    [](JsonObject &row) { row["temperature"] = readTemperature(); });
```

## 3. Read it back

Fetch recent rows from firmware:

```cpp theme={null}
device.getDatabaseData(productId, "readings", 20);   // latest 20
```

Or display them on a dashboard with a **Table** or **Dynamic Repeater** widget
bound to the table. The Script API's [`db.query`](/script/database-api) does the
same client-side.

<Note>
  Update and delete are available too: `updateDatabaseData(dataId, …)` and
  `deleteDatabaseData(dataId)` (each with a `…WithResponse` form). See the
  [API reference](/firmware/arduino/api-reference#database).
</Note>

<Card title="Next: publish & onboard" icon="arrow-right" href="/learn/lessons/05-publish-onboard">
  Ship it to users.
</Card>
