// Edge-control-plane schema, authored by ace-ng-edge team, reviewed
// + accepted by Aerodrome 2026-04-22. Generalized to multi-protocol
// (BACnet + Modbus + EtherNet/IP) per the multi-protocol parity
// plan; see `multi-protocol-config-parity.md` in the Aerodrome repo.
//
// Storage: edge.config KV under registry.{device_id} (ULID string).
// Cloud-to-edge delivery: ace.edge.cmd.config.update (see commands.proto).

syntax = "proto3";

package aerodrome.v1;

import "aerodrome/v1/bacnet.proto";
import "aerodrome/v1/driver_type.proto";
import "aerodrome/v1/ethernet_ip.proto";
import "aerodrome/v1/modbus.proto";

// Fields every PointDef carries regardless of protocol. The cloud
// uses these to drive cadence, the edge respects them on every
// poll cycle.
message CommonPointFields {
  // Aerodrome DataPoint UUID this point projects from. The
  // (deployment_id, device_id, datapoint_id) tuple is the dedup
  // key on the canonical side.
  string datapoint_id = 1;

  // Aerodrome timeseries node UUID. Empty string = not mapped,
  // edge loads the point but doesn't publish telemetry.
  string timeseries_id = 2;

  // Cadence triple (seconds, float). Defaults: 5.0 / 300.0 / 10.0.
  double min_interval = 3;
  double max_interval = 4;
  double max_age = 5;

  // Whether the edge accepts writes on this point. Modbus
  // input/discrete registers can never be writable regardless of
  // this field; the cloud validator rejects writable=true on
  // those.
  bool writable = 6;
}

// Tagged per-protocol point definition. `address` discriminates
// by protocol; common fields live alongside so callers don't need
// to dispatch on the variant just to read the cadence.
message PointDef {
  CommonPointFields common = 1;

  oneof address {
    BacnetPointAddress bacnet = 10;
    ModbusPointAddress modbus = 11;
    EthernetIpPointAddress ethernet_ip = 12;
  }
}

// Point registry for a single device. The driver reads this to
// know which points to poll and publish telemetry for. One row
// per device in edge.config under registry.{device_id}.
message RegistryConfig {
  // ULID device handle, matching the driver-config row's
  // device_id. Must equal the `{device_id}` token in the KV key;
  // duplicated here so payloads are self-describing on the wire.
  string device_id = 1;

  // Protocol family for the points below. Required. Cloud
  // validator rejects mismatches (e.g. driver_type=modbus with a
  // BacnetPointAddress point).
  DriverType driver_type = 3;

  // Points to poll / publish. Empty list is valid — represents a
  // discovered device with no points mapped yet. The driver loads
  // it, emits reachability, but publishes no telemetry.
  repeated PointDef points = 2;
}
