# Meter and industrial protocols

These are the protocols where **OpenGate opens the conversation**. There is no south endpoint waiting for the
device: a [connector function](../connector_functions/) reaches out, talks the protocol, and turns the answer
into data points or an operation result.

## The polling model

```mermaid
flowchart TB
    JOB["A job or task<br>launches an operation"] --> REQ["REQUEST connector function"]
    REQ -->|"opens the connection"| DEV["Meter or network device"]
    DEV -->|"attribute values"| REQ
    REQ --> OUT["Operation result<br>and collected data points"]

    classDef cf fill:#addcf8,stroke:#2b7cb8,color:#000,font-weight:bold
    class REQ cf
```

Three consequences worth planning for:

- **The device must be reachable** at an IP address: directly, over a VPN, or through a
  [gateway](../topology/) using a path.
- **Reading is an operation.** You schedule meter readings with [jobs and tasks](../../operations/), which
  is also how you get retries, timeouts and per-device results.
- **Connection parameters live in your script**, taken from the device's provisioned data. Keep credentials
  out of the code: read them from the `entity` object.

## DLMS

The only protocol here that works in **both directions**.

| Direction | What happens |
|---|---|
| Device to platform | The meter sends a DLMS message. A `COLLECTION` connector function receives it, with the `obisCode` and `templateId` of the message in `contextParams` and the attribute values in `payload` |
| Platform to device | `dlms.connect()` opens a session, then `dlms.addAttr()` builds a list of attributes by class id, OBIS code and attribute id, and `dlms.get()` or `dlms.set()` executes it |

Attributes are addressed the DLMS way — a class id, an OBIS code and an attribute id — and values carry
explicit DLMS types such as `octet-string`, which the reference explains how to convert to dates and back.

**Reference**: [DLMS JavaScript API](../connector_functions/protocol_apis/dlms/)

### DLMS Gas

Smart Gas meters differ enough between manufacturers to make a generic DLMS script painful. `dlms_gas`
absorbs that: it carries per-manufacturer behaviours — currently `pietro`, `watertech`, `honeywell` and
`spark` — over a common default, and is designed to be extended with new ones.

A standard function becomes about four calls:

```javascript
dlms_gas.init();
dlms_gas.decode();
dlms_gas.pendingActions();
```

**Reference**: [DLMS Gas JavaScript API](../connector_functions/protocol_apis/dlms_gas/)

## IEC102

Electricity meters. `iec102.connect(registerType)` does more than open a socket:

| `registerType` | Meaning |
|---|---|
| `IP` | Direct IP connection. The default when you do not specify one |
| `VPN` | Through a VPN |
| `GSM` | Over a GSM call, sending the commands needed to register |
| `ATR` | Over ATR, likewise |

With `GSM` or `ATR`, connecting also collects a presence data point,
`device.communicationModules[].subscription.mobile.presence.gsm`, with `OK` or `NOK` — so the attempt itself
tells you whether the meter is alive.

Connection properties are set on the object before connecting:

```javascript
iec102.ip = "127.0.0.1";
iec102.port = "3000";
iec102.linkAddress = "1";
iec102.useMeasurePoint = "1";
```

{{% notice style="primary" title="Always check the status after connecting" icon="triangle-exclamation" %}}
On failure, `connect` sets the `response` status to `ERROR_PROCESSING` with the error description. Check the
returned status and return the `response` object instead of carrying on — otherwise the operation reports
something misleading.
{{% /notice %}}

Once connected, work is expressed as **ASDUs**: clock reading, load curves, profiles. They can be executed
directly, defined from the operation's parameters, or declared by hand.

**Reference**: [IEC102 JavaScript API](../connector_functions/protocol_apis/iec102/)

## SNMP

Network equipment. Build a list of OIDs with `snmp.addOid()`, then run `snmp.get()` or `snmp.set()`.

To store what you read, hand it to a collection with the `snmps://` scheme, which is also what a
`COLLECTION` function matches as its south criteria:

```javascript
collectCF(result.data, "snmps://<oidValue>");
```

**Reference**: [SNMP JavaScript API](../connector_functions/protocol_apis/snmp/)

## Where to go next

| To | Read |
|---|---|
| See every protocol OpenGate speaks, and which side calls | [Supported protocols](../supported_protocols/) |
| Write the function that does the talking | [Connector Functions](../connector_functions/) |
| Schedule readings across a fleet | [Jobs and tasks](../../operations/) |
| Reach a meter behind a gateway | [Topology](../topology/) |
| Watch a function run | [Debugging](../../debugging/) |
