# SNMP and Modbus

SNMP definitions support v2c and v3 devices. Communities, authentication keys,
and privacy keys are installation bindings. Poll groups define intervals, numeric
dotted OIDs or walks, and their handler. Authentication and privacy algorithms
must form a valid combination.

```xml
<edge-app format="1" handle="network-monitor" name="Network monitor">
  <config-schema>
    <schema type="object" xmlns="urn:cococo:json-schema:1">
      <additional-properties boolean="false"/>
      <property name="LEGACY_SWITCH_HOST" type="string"/>
      <property name="SECURE_SWITCH_HOST" type="string"/>
      <property name="SNMP_AUTH_KEY" type="string" write-only="true"/>
      <property name="SNMP_COMMUNITY" type="string" write-only="true"/>
      <property name="SNMP_PRIVACY_KEY" type="string" write-only="true"/>
      <property name="SNMP_USER" type="string"/>
      <required name="LEGACY_SWITCH_HOST"/>
      <required name="SECURE_SWITCH_HOST"/>
      <required name="SNMP_COMMUNITY"/>
      <required name="SNMP_USER"/>
      <required name="SNMP_AUTH_KEY"/>
      <required name="SNMP_PRIVACY_KEY"/>
    </schema>
  </config-schema>
  <handlers>
    <handler name="polled"><![CDATA[
return params.values
    ]]></handler>
  </handlers>
  <snmp-devices>
    <device name="legacy-switch" host="${config:LEGACY_SWITCH_HOST}" port="161" version="v2c" timeout-ms="2000" retries="3">
      <community config="SNMP_COMMUNITY"/>
      <poll-groups>
        <poll name="health" interval-ms="5000" handler="polled">
          <oid label="uptime" value="1.3.6.1.2.1.1.3.0"/>
          <walk label="interfaces" value="1.3.6.1.2.1.2.2"/>
        </poll>
      </poll-groups>
    </device>
    <device name="secure-switch" host="${config:SECURE_SWITCH_HOST}" version="v3">
      <v3 user="${config:SNMP_USER}" auth-protocol="sha256" privacy-protocol="aes128">
        <auth-key config="SNMP_AUTH_KEY"/>
        <privacy-key config="SNMP_PRIVACY_KEY"/>
      </v3>
      <poll-groups>
        <poll name="health" interval-ms="5000" handler="polled">
          <oid label="uptime" value="1.3.6.1.2.1.1.3.0"/>
        </poll>
      </poll-groups>
    </device>
  </snmp-devices>
</edge-app>
```

Modbus definitions support TCP, RTU over TCP, and serial RTU. Ports contain slave
units and poll groups with typed reads. The compiler checks transport-specific
fields, unit IDs, address ranges, function/type compatibility, and register
quantities.

```xml
<edge-app format="1" handle="drive-monitor" name="Drive monitor">
  <config-schema>
    <schema type="object" xmlns="urn:cococo:json-schema:1">
      <additional-properties boolean="false"/>
      <property name="MODBUS_HOST" type="string"/>
      <property name="MODBUS_SERIAL_PATH" type="string"/>
      <required name="MODBUS_HOST"/>
      <required name="MODBUS_SERIAL_PATH"/>
    </schema>
  </config-schema>
  <handlers>
    <handler name="polled"><![CDATA[
return params.values
    ]]></handler>
  </handlers>
  <modbus-ports>
    <port name="tcp-bus" transport="tcp" host="${config:MODBUS_HOST}" port="502">
      <slaves>
        <slave name="drive-1" unit-id="1">
          <poll-groups>
            <poll name="vitals" interval-ms="1000" handler="polled">
              <read label="speed" function="holding" address="100" quantity="2" type="float32" scale="0.1" word-order="high" byte-order="big"/>
              <read label="running" function="coils" address="12" quantity="1" type="bool"/>
            </poll>
          </poll-groups>
        </slave>
      </slaves>
    </port>
    <port name="serial-bus" transport="rtu" serial-path="${config:MODBUS_SERIAL_PATH}" baud-rate="19200" parity="even" stop-bits="1" data-bits="8">
      <slaves>
        <slave name="meter" unit-id="2">
          <poll-groups>
            <poll name="energy" interval-ms="5000" handler="polled">
              <read label="total" function="input" address="200" quantity="2" type="uint32" word-order="low"/>
            </poll>
          </poll-groups>
        </slave>
      </slaves>
    </port>
  </modbus-ports>
</edge-app>
```