# NI digital read task

> Learn how to acquire digital data from NI devices with Synnax.

This task follows the standard [task lifecycle](https://docs.synnaxlabs.com/reference/driver/task-basics#task-lifecycle).

## Task configuration reference

| Parameter     | Type   | Required | Default | Description                                                   |
| ------------- | ------ | -------- | ------- | ------------------------------------------------------------- |
| `device`      | string | Yes      | -       | Device key to read from                                       |
| `sample_rate` | number | No       | `10`    | Samples per second (Hz)                                       |
| `stream_rate` | number | No       | `5`     | Rate data is streamed to Synnax (Hz), must be ≤ `sample_rate` |
| `channels`    | array  | Yes      | -       | List of digital input channel configurations                  |

## Channel configuration reference

[DI Channel NI-DAQmx C API Reference](https://www.ni.com/docs/en-US/bundle/ni-daqmx-c-api-ref/page/group__ni-daqmx__c__functions__channel__configuration__creation__create__digital__input__channels_1ga3325b4a3660e51e9d6631460bab3ed94.html)

| Parameter | Type   | Required | Default | Description                               |
| --------- | ------ | -------- | ------- | ----------------------------------------- |
| `channel` | number | Yes      | -       | Synnax channel key for digital input data |
| `port`    | number | Yes      | -       | Physical port                             |
| `line`    | number | Yes      | -       | Line number on the port                   |

## Important rules

* **One task per module** -> Only one running task can claim a module at a time.
* **Stream rate** -> For sample rates under 50 Hz, set the stream rate equal to the sample rate. Above that, keep the stream rate under 50 Hz.

## How-to

**Console**

[](https://synnax.nyc3.cdn.digitaloceanspaces.com/docs/device-drivers/ni/digital-read-task/ni-digital-read-dark.mp4#t=0.001)

**Python**

Configure and run task

```python
import synnax as sy
from synnax import ni

client = sy.Synnax()

# Retrieve device
digital_dev = client.devices.retrieve(name="Mod1_Digital")

# Create index channel
di_time = client.channels.create(
    name="di_time",
    is_index=True,
    data_type=sy.DataType.TIMESTAMP,
    retrieve_if_name_exists=True,
)

# Create data channels
di_0_0 = client.channels.create(
    name="di_0_0",
    index=di_time.key,
    data_type=sy.DataType.UINT8,
    retrieve_if_name_exists=True,
)
di_0_1 = client.channels.create(
    name="di_0_1",
    index=di_time.key,
    data_type=sy.DataType.UINT8,
    retrieve_if_name_exists=True,
)
di_1_0 = client.channels.create(
    name="di_1_0",
    index=di_time.key,
    data_type=sy.DataType.UINT8,
    retrieve_if_name_exists=True,
)

# Create and configure task
task = ni.DigitalReadTask(
    name="NI Digital Read Task",
    device=digital_dev.key,
    sample_rate=sy.Rate.HZ * 100,
    stream_rate=sy.Rate.HZ * 25,
    channels=[
        ni.DIChannel(
            channel=di_0_0.key,
            port=0,
            line=0,
        ),
        ni.DIChannel(
            channel=di_0_1.key,
            port=0,
            line=1,
        ),
        ni.DIChannel(
            channel=di_1_0.key,
            port=1,
            line=0,
        ),
    ],
)

client.tasks.configure(task)

# Start task and read data
with task.run():
    with client.open_streamer(["di_0_0", "di_0_1", "di_1_0"]) as streamer:
        for _ in range(10):
            frame = streamer.read()
            print(frame)
```

Edit task configuration

```python
# Retrieve existing task
task = client.tasks.retrieve(name="NI Digital Read Task")
task = ni.DigitalReadTask(internal=task)

# Update task-level configuration
task.config.auto_start = True
task.config.stream_rate = int(sy.Rate.HZ * 50)

# Update first channel configuration
task.config.channels[0].port = 0
task.config.channels[0].line = 2

# Update second channel configuration
task.config.channels[1].port = 0
task.config.channels[1].line = 3

# Update third channel configuration
task.config.channels[2].port = 1
task.config.channels[2].line = 1

# Apply changes
client.tasks.configure(task)
```

**TypeScript**

Configure and run task

```typescript
import { Synnax } from "@synnaxlabs/client";

const client = new Synnax();

// Retrieve device
const [digitalDev] = await client.devices.retrieve({ names: ["Mod1_Digital"] });

// Create index channel
const diTime = await client.channels.create(
  {
    name: "di_time",
    isIndex: true,
    dataType: "timestamp",
  },
  { retrieveIfNameExists: true },
);

// Create data channels
const di00 = await client.channels.create(
  {
    name: "di_0_0",
    index: diTime.key,
    dataType: "uint8",
  },
  { retrieveIfNameExists: true },
);

const di01 = await client.channels.create(
  {
    name: "di_0_1",
    index: diTime.key,
    dataType: "uint8",
  },
  { retrieveIfNameExists: true },
);

const di10 = await client.channels.create(
  {
    name: "di_1_0",
    index: diTime.key,
    dataType: "uint8",
  },
  { retrieveIfNameExists: true },
);

// Create and configure task
const task = await client.tasks.create({
  name: "NI Digital Read Task",
  rack: digitalDev.rack,
  type: "ni_digital_read",
  config: {
    device: digitalDev.key,
    sampleRate: 100,
    streamRate: 25,
    channels: [
      {
        channel: di00.key,
        port: 0,
        line: 0,
      },
      {
        channel: di01.key,
        port: 0,
        line: 1,
      },
      {
        channel: di10.key,
        port: 1,
        line: 0,
      },
    ],
  },
});

// Start task
await task.start();

// Read data
const streamer = await client.openStreamer(["di_0_0", "di_0_1", "di_1_0"]);
for (let i = 0; i < 10; i++) {
  const frame = await streamer.read();
  console.log(frame);
}

// Stop task
await task.stop();
await streamer.close();
```

Edit task configuration

```typescript
import { ni } from "@synnaxlabs/client";

// Retrieve existing task
const task = await client.tasks.retrieve({ name: "NI Digital Read Task" });

// Parse and update configuration
const config = ni.digitalReadConfigZ.parse(task.config);

// Update task-level configuration
config.autoStart = true;
config.streamRate = 50;

// Update first channel configuration
config.channels[0].port = 0;
config.channels[0].line = 2;

// Update second channel configuration
config.channels[1].port = 0;
config.channels[1].line = 3;

// Update third channel configuration
config.channels[2].port = 1;
config.channels[2].line = 1;

// Apply changes
await client.tasks.create({
  key: task.key,
  rack: task.rack,
  name: task.name,
  type: task.type,
  config,
});
```
