> For the complete documentation index, see [llms.txt](https://docs.protoboard.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.protoboard.xyz/reference/interfaces-and-harnesses.md).

# Interfaces and Harnesses

How parts declare connection intent through interfaces, how harnesses bundle them, and the protocol compatibility rules that make it all work.

Interfaces and harnesses are the connection layer of Protoboard. An **interface** is a single, typed connection point declared by a part. A **harness** is the logical cable that groups every interface link between two parts into one bundle. Together they let Protoboard automatically discover which parts can talk to each other, allocate the right physical resources, and flag mismatches before you build anything.

***

## Core Concepts

### What Is an Interface?

An interface is a **template for exactly one connection** between two devices. It declares:

1. **Protocol**: what language it speaks (e.g., `i2c`, `power`, `pneumatic`).
2. **Role**: which side of the conversation it is on (e.g., `master` vs `slave`).
3. **Required functions**: which physical resource capabilities it needs (e.g., `i2c_sda` x1, `i2c_scl` x1).

{% hint style="info" %}
**The golden rule: 1 interface = 1 connection.**\
One interface goes between exactly two devices. If signals always travel together on one physical connector, that is one interface. If any wire could reasonably be routed to a different destination, split it into a separate interface.
{% endhint %}

### What Is a Harness?

A harness is the **single logical cable** between two parts. When you drag a connection on the canvas, Protoboard creates a harness and then discovers which interfaces on each side are compatible. Compatible pairs become **interface links** inside the harness.

To the user a harness looks like one line in the system diagram. Under the hood it carries all the mapped signals, power rails, or fluid channels between those two parts.

### What Is a Function Link?

Within an interface link, each required function on one side is matched to a required function on the other side. These individual pairings are **function links**. For example, an I2C interface link contains two function links: one for SDA and one for SCL.

***

## The Protocol + Role System

Two interfaces can connect **only** when:

1. Their `protocol.type` values are **identical** (case-sensitive string match).
2. Their `protocol.role` values form a **compatible pair**.

### Protocol Types by Domain

{% tabs %}
{% tab title="Electrical" %}

| Protocol Type      | Typical Roles                                                   | Topology         | Notes                              |
| ------------------ | --------------------------------------------------------------- | ---------------- | ---------------------------------- |
| `power`            | `input` / `output`, `source` / `sink`                           | Point-to-point   | Generic power delivery.            |
| `dc_power`         | `input` / `output`, `source` / `sink`                           | Point-to-point   | Explicit DC power.                 |
| `digital`          | `transmitter` / `receiver`, `output` / `input`, `peer` / `peer` | Point-to-point   | Single digital signal.             |
| `gpio`             | `input` / `output`, `peer` / `peer`                             | Point-to-point   | General purpose I/O.               |
| `pwm`              | `transmitter` / `receiver`, `output` / `input`                  | Point-to-point   | Pulse-width modulation.            |
| `analog`           | `transmitter` / `receiver`, `output` / `input`                  | Point-to-point   | Analog signal.                     |
| `i2c`              | `master` / `slave`                                              | Bus              | 2-wire, up to \~8 devices typical. |
| `spi`              | `master` / `slave`                                              | Multi-drop w/ SS | 4-wire (MOSI, MISO, SCK, SS).      |
| `uart`             | `host` / `device`, `peer` / `peer`                              | Point-to-point   | Serial TX/RX.                      |
| `can`              | `peer` / `peer`                                                 | Bus              | CAN-H / CAN-L differential.        |
| `usb`              | `host` / `device`                                               | Point-to-point   | D+, D-, GND, VBUS.                 |
| `ethernet`         | `host` / `device`, `peer` / `peer`                              | Point-to-point   | Physical Ethernet (TXD, RXD).      |
| `brushless_3phase` | `driver` / `motor`                                              | Point-to-point   | 3 phases (A, B, C).                |
| `dc_motor`         | `driver` / `actuator`                                           | Point-to-point   | Motor +/-.                         |
| `servo_control`    | `controller` / `actuator`                                       | Point-to-point   | PWM servo signal.                  |
| `quadrature`       | `encoder` / `receiver`                                          | Point-to-point   | A/B channels.                      |
| `swd_debug`        | `debugger` / `target`                                           | Point-to-point   | SWDIO + SWCLK.                     |
| {% endtab %}       |                                                                 |                  |                                    |

{% tab title="Mechanical" %}

| Protocol Type           | Typical Roles                                          | Notes                     |
| ----------------------- | ------------------------------------------------------ | ------------------------- |
| `threaded_connection`   | `mounting_point`, `structural_support`, `panel_mount`  | Screws, bolts, standoffs. |
| `clip_connection`       | `mounting_point`, `structural_support`, `panel_mount`  | Snap-fit, clip-on.        |
| `mechanical_connection` | `mounting_point`, `structural_support`, `cable_anchor` | General mechanical.       |
| `mechanical_attachment` | `mounting_point`, `structural_support`                 | Simple attachment.        |
| `mechanical_rotation`   | `shaft`, `driver`                                      | Rotating couplings.       |
| `mechanical_spline`     | `shaft`, `driver`                                      | Spline couplings.         |
| `arduino_uno_shield`    | `shield`, `arduino`                                    | Arduino form-factor.      |
| `pi hat`                | `shield`, `host`                                       | Raspberry Pi HAT.         |
| {% endtab %}            |                                                        |                           |

{% tab title="Thermal" %}

| Protocol Type        | Typical Roles                    | Notes               |
| -------------------- | -------------------------------- | ------------------- |
| `thermal_connection` | `thermal_source`, `thermal_sink` | Heat transfer path. |
| {% endtab %}         |                                  |                     |

{% tab title="Fluid (Pneumatic / Hydraulic)" %}

| Protocol Type   | Typical Roles                                                                                    | Notes                   |
| --------------- | ------------------------------------------------------------------------------------------------ | ----------------------- |
| `pneumatic`     | `supply`, `return`, `exhaust`, `control`, `sensing`, `filter`, `regulator`, `valve`, `reservoir` | Compressed air systems. |
| `hydraulic`     | `supply`, `return`, `control`, `sensing`, `filter`, `regulator`, `valve`, `reservoir`            | Hydraulic oil systems.  |
| `vacuum`        | `supply`, `return`, `exhaust`, `sensing`, `filter`, `regulator`, `valve`, `reservoir`            | Vacuum systems.         |
| `gas_supply`    | `supply`, `return`, `sensing`, `regulator`, `valve`, `filter`, `reservoir`                       | Gas delivery.           |
| `liquid_supply` | `supply`, `return`, `sensing`, `regulator`, `valve`, `filter`, `reservoir`                       | Liquid delivery.        |
| `drain`         | `return`, `exhaust`                                                                              | Drain outlet.           |
| `vent`          | `exhaust`                                                                                        | Atmospheric vent.       |
| {% endtab %}    |                                                                                                  |                         |

{% tab title="Network" %}

| Protocol Type                    | Typical Roles                              | Notes                        |
| -------------------------------- | ------------------------------------------ | ---------------------------- |
| `ethernet`                       | `bridge`, `access_point`, `client`, `peer` | Layer 2/3 networking.        |
| `power_over_ethernet`            | `bridge`, `access_point`, `client`         | PoE with power + data.       |
| `wifi`                           | `access_point`, `client`, `peer`           | Wireless LAN.                |
| `bluetooth`                      | `master`, `slave`, `peer`                  | BT Classic and BLE.          |
| `mqtt`, `http`, `https`, `ssh`   | `client`, `server`, `peer`                 | Application-layer protocols. |
| `modbus`, `profinet`, `ethercat` | `master`, `slave`, `coordinator`           | Industrial protocols.        |
| {% endtab %}                     |                                            |                              |
| {% endtabs %}                    |                                            |                              |

***

## Role Compatibility Pairs

Two interfaces connect when their roles form a recognized pair. The table below covers all built-in pairings grouped by domain.

### Electrical Role Pairs

| Role A        | Role B     | Used By                                          |
| ------------- | ---------- | ------------------------------------------------ |
| `output`      | `input`    | `power`, `digital`, `gpio`, `pwm`, `analog`      |
| `source`      | `sink`     | `power`, `dc_power`                              |
| `transmitter` | `receiver` | `digital`, `pwm`, `analog`, `quadrature`         |
| `master`      | `slave`    | `i2c`, `spi`, `bluetooth`                        |
| `host`        | `device`   | `uart`, `usb`, `ethernet`                        |
| `peer`        | `peer`     | `uart`, `can`, `digital`, `gpio`, `ethernet`     |
| `driver`      | `motor`    | `brushless_3phase`, `bipolar_stepper_phases`     |
| `driver`      | `actuator` | `dc_motor`, `stepper_motor`, `stepper_pulse_dir` |
| `controller`  | `actuator` | `servo_control`                                  |
| `encoder`     | `receiver` | `quadrature`                                     |
| `sensor`      | `receiver` | `hall_encoder`                                   |
| `debugger`    | `target`   | `swd_debug`                                      |
| `transceiver` | `antenna`  | `nfc_antenna`                                    |

### Mechanical Role Pairs

| Role A   | Role B    | Used By                                    |
| -------- | --------- | ------------------------------------------ |
| `shaft`  | `driver`  | `mechanical_rotation`, `mechanical_spline` |
| `shield` | `arduino` | `arduino_uno_shield`                       |
| `shield` | `host`    | `pi hat`                                   |

### Thermal Role Pairs

| Role A           | Role B         | Used By              |
| ---------------- | -------------- | -------------------- |
| `thermal_source` | `thermal_sink` | `thermal_connection` |

### Fluid Role Pairs

| Role A      | Role B    | Used By                                                           |
| ----------- | --------- | ----------------------------------------------------------------- |
| `supply`    | `return`  | `pneumatic`, `hydraulic`, `vacuum`, `gas_supply`, `liquid_supply` |
| `supply`    | `control` | `pneumatic`, `hydraulic`                                          |
| `supply`    | `exhaust` | `vacuum`                                                          |
| `regulator` | `supply`  | All fluid protocols                                               |
| `valve`     | `supply`  | All fluid protocols                                               |

### Network Role Pairs

| Role A         | Role B   | Used By                                   |
| -------------- | -------- | ----------------------------------------- |
| `bridge`       | `bridge` | `ethernet`                                |
| `bridge`       | `client` | `ethernet`, `power_over_ethernet`         |
| `access_point` | `client` | `ethernet`, `wifi`, `power_over_ethernet` |
| `peer`         | `peer`   | `ethernet`, `wifi`                        |
| `master`       | `slave`  | `bluetooth`                               |

{% hint style="warning" %}
**Role aliases exist.** The protocol spec normalizes common variants automatically:\
`controller` -> `master`, `target` -> `slave`, `serial` -> `uart`, `can_bus` -> `can`.\
But in your definition files, prefer the canonical names listed above.
{% endhint %}

***

## How Connections Work: Step by Step

{% stepper %}
{% step %}

#### Harness creation

When you connect two parts on the canvas, Protoboard creates a **harness**, the logical bundle between them.
{% endstep %}

{% step %}

#### Interface discovery

The engine loads both part definitions and extracts every interface from every domain.
{% endstep %}

{% step %}

#### Compatibility matrix

Every interface on part A is compared against every interface on part B. A pair is compatible when their `protocol.type` matches **and** their `role` values form a recognized pair.
{% endstep %}

{% step %}

#### Resource feasibility check

For each compatible pair, the engine checks whether enough **unallocated resources** exist on both sides to satisfy the `requires` arrays.
{% endstep %}

{% step %}

#### Auto-linking

Compatible pairs with available resources are automatically linked inside the harness. Each link maps specific resource functions on one side to resource functions on the other.
{% endstep %}

{% step %}

#### Resource allocation

The allocation engine binds physical resources to the linked functions. A resource claimed by one interface link is no longer available for others (unless `shareable_with` allows it).
{% endstep %}
{% endstepper %}

***

## Resource Allocation Model

### Exclusive by Default

When an interface claims a resource for a function, that resource is **exclusively allocated**; no other interface can use it. This is the safe default and matches how most physical pins work.

### Shareable Resources

Some resources legitimately serve multiple functions simultaneously. The `shareable_with` field unlocks this:

```json
{
  "id": "rj45_port_1",
  "functions": [
    { "name": "ethernet_port", "shareable_with": ["poe_power_source"] },
    { "name": "poe_power_source", "shareable_with": ["ethernet_port"] }
  ]
}
```

Here a single RJ45 jack can carry both Ethernet data and PoE power at the same time. Both functions list each other in `shareable_with`, so a network interface and a power interface can both claim this resource.

### Allocation Rules

{% hint style="danger" %}
**One resource = one function at a time** (unless shareable). The allocation engine finds resources **by function name**. When an interface requires multiple functions, it searches for a **separate resource** for each one. Bundling multiple pins into one resource will cause allocation failures.
{% endhint %}

| Scenario                              | Correct Approach                                           |
| ------------------------------------- | ---------------------------------------------------------- |
| I2C bus (SDA + SCL)                   | Two resources: one with `i2c_sda`, one with `i2c_scl`.     |
| 3-phase motor (A, B, C)               | Three resources: `phase_a`, `phase_b`, `phase_c`.          |
| Pin with multiple alternate functions | One resource with multiple functions (mutually exclusive). |
| PoE port (data + power on same jack)  | One resource with `shareable_with` between functions.      |

***

## Multi-Domain Interfaces

Some real-world connections span multiple domains. A Power-over-Ethernet switch, for example, needs interfaces in both the `electrical` and `network` domains.

When an interface spans domains, **reuse the same protocol identifier** in each relevant domain. This keeps allocation synchronized. If the protocol (e.g., `power_over_ethernet`) does not exist in the protocol spec yet, request it from the ProtoPart team or add it yourself before using it in component files.

***

## Interface Constraints

### `max_instances`

Limits how many times the device can instantiate this interface. Use **only** when the hardware itself imposes a limit beyond what resources would allow.

| Example                       | Reason                                                              |
| ----------------------------- | ------------------------------------------------------------------- |
| MCU with 1 I2C controller     | `max_instances: 1` on the I2C master interface.                     |
| MCU with 2 UART peripherals   | `max_instances: 2` on the UART interface.                           |
| Sensor with 8 analog channels | Let the system calculate from resources; no `max_instances` needed. |

### `max_connections`

Limits how many **other parts** can connect to a single interface instance. This is about electrical, structural, or protocol load limits.

| Example         | Value | Reason                  |
| --------------- | ----- | ----------------------- |
| I2C bus         | `8`   | Capacitance limits.     |
| Power output    | `10`  | Current sharing.        |
| SPI chip select | `1`   | One device per SS line. |

### Voltage Domain Matching

When `requires_matching_voltage_domain` is `true`, both sides of a connection must reference power domains with overlapping voltage ranges. This prevents connecting a 3.3V sensor directly to a 12V output.

***

## Common Interface Patterns

{% tabs %}
{% tab title="I2C" %}
**Master side** (e.g., Arduino Nano):

```json
{
  "id": "i2c_master",
  "protocol": { "type": "i2c", "role": "master" },
  "requires": [
    { "function": "i2c_sda", "count": 1 },
    { "function": "i2c_scl", "count": 1 }
  ],
  "constraints": { "max_connections": 8, "requires_matching_voltage_domain": true }
}
```

**Slave side** (e.g., BME280 sensor):

```json
{
  "id": "i2c_slave",
  "protocol": { "type": "i2c", "role": "slave" },
  "requires": [
    { "function": "i2c_sda", "count": 1 },
    { "function": "i2c_scl", "count": 1 }
  ],
  "constraints": { "requires_matching_voltage_domain": true }
}
```

Compatibility: `master` pairs with `slave`. Both require the same functions, so function links map `i2c_sda` to `i2c_sda` and `i2c_scl` to `i2c_scl`.
{% endtab %}

{% tab title="SPI" %}
**Master side:**

```json
{
  "id": "spi_master",
  "protocol": { "type": "spi", "role": "master" },
  "requires": [
    { "function": "spi_mosi", "count": 1 },
    { "function": "spi_miso", "count": 1 },
    { "function": "spi_sck", "count": 1 },
    { "function": "spi_ss", "count": 1 }
  ]
}
```

**Slave side:**

```json
{
  "id": "spi_slave",
  "protocol": { "type": "spi", "role": "slave" },
  "requires": [
    { "function": "spi_mosi", "count": 1 },
    { "function": "spi_miso", "count": 1 },
    { "function": "spi_sck", "count": 1 },
    { "function": "spi_ss", "count": 1 }
  ]
}
```

{% endtab %}

{% tab title="UART" %}

```json
{
  "id": "uart_host",
  "protocol": { "type": "uart", "role": "host" },
  "requires": [
    { "function": "uart_tx", "count": 1 },
    { "function": "uart_rx", "count": 1 }
  ]
}
```

Pairs with:

```json
{
  "id": "uart_device",
  "protocol": { "type": "uart", "role": "device" },
  "requires": [
    { "function": "uart_tx", "count": 1 },
    { "function": "uart_rx", "count": 1 }
  ]
}
```

Note: UART TX on one side connects to RX on the other; the function link handles the crossover.
{% endtab %}

{% tab title="Power" %}

```json
{
  "id": "power_output",
  "protocol": { "type": "power", "role": "output" },
  "requires": [
    { "function": "power_output", "count": 1 },
    { "function": "ground", "count": 1 }
  ],
  "constraints": { "max_connections": 10 },
  "power_delivery": {
    "max_voltage_V": 5,
    "max_current_mA": 800
  }
}
```

Pairs with any `power` / `input` interface.
{% endtab %}

{% tab title="Pneumatic" %}
**Supply side** (compressor or regulator output):

```json
{
  "id": "air_supply",
  "protocol": { "type": "pneumatic", "role": "supply" },
  "requires": [
    { "function": "pressure_port", "count": 1 }
  ],
  "system_pressure_bar": 6.9
}
```

**Return side** (actuator input):

```json
{
  "id": "air_input",
  "protocol": { "type": "pneumatic", "role": "return" },
  "requires": [
    { "function": "return_port", "count": 1 }
  ]
}
```

{% endtab %}
{% endtabs %}

***

## Best Practices

{% hint style="success" %}
**Use standard protocol types.** Custom protocol names will not match any existing parts. If you need a new protocol, add it to `protocol-spec-vX.X.X.json` or request it from the ProtoPart team.
{% endhint %}

* **Treat the physical connector as the boundary.** One plug or cable = one interface. If any pin group could be separated, split it now.
* **Define both high-level and low-level interfaces.** A motor control interface (2 digital + 1 PWM) can coexist with separate digital and PWM interfaces on the same resources.
* **Use specific roles**, not generic ones. `"input"` / `"output"` is far better than `"connection"`.
* **Let the system calculate instances.** Only set `max_instances` when the hardware itself limits the count beyond what resources allow.
* **Keep interfaces fully specified.** Include direction, voltage constraints, protocol timing, and mechanical keying where applicable.
* **One resource per allocatable unit.** Never wrap multiple wires into a single resource.


---

# 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://docs.protoboard.xyz/reference/interfaces-and-harnesses.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.
