// Frequenz microgrid components definitions.
//
// Copyright:
// Copyright 2023 Frequenz Energy-as-a-Service GmbH
//
// License:
// MIT

syntax = "proto3";

package frequenz.api.common.v1.microgrid.components;

import "frequenz/api/common/v1/metrics/bounds.proto";
import "frequenz/api/common/v1/metrics/metric_sample.proto";
import "frequenz/api/common/v1/microgrid/components/battery.proto";
import "frequenz/api/common/v1/microgrid/components/ev_charger.proto";
import "frequenz/api/common/v1/microgrid/components/fuse.proto";
import "frequenz/api/common/v1/microgrid/components/grid.proto";
import "frequenz/api/common/v1/microgrid/components/inverter.proto";
import "frequenz/api/common/v1/microgrid/components/transformer.proto";
import "frequenz/api/common/v1/microgrid/lifetime.proto";

import "google/protobuf/timestamp.proto";

// Enumrated component categories.
enum ComponentCategory {
  // An unknown component categories, useful for error handling, and marking
  // unknown components in a list of components with otherwise known categories.
  COMPONENT_CATEGORY_UNSPECIFIED = 0;

  // The point where the local microgrid is connected to the grid.
  COMPONENT_CATEGORY_GRID = 1;

  // A meter, for measuring electrical metrics, e.g., current, voltage, etc.
  COMPONENT_CATEGORY_METER = 2;

  // An electricity generator, with batteries or solar energy.
  COMPONENT_CATEGORY_INVERTER = 3;

  // A DC-DC converter.
  COMPONENT_CATEGORY_CONVERTER = 4;

  // A storage system for electrical energy, used by inverters.
  COMPONENT_CATEGORY_BATTERY = 5;

  // A station for charging electrical vehicles.
  COMPONENT_CATEGORY_EV_CHARGER = 6;

  // A crypto miner.
  COMPONENT_CATEGORY_CRYPTO_MINER = 8;

  // An electrolyzer for converting water into hydrogen and oxygen.
  COMPONENT_CATEGORY_ELECTROLYZER = 9;

  // A heat and power combustion plant (CHP stands for combined heat and power).
  COMPONENT_CATEGORY_CHP = 10;

  // A relay.
  // Relays generally have two states: open (connected) and closed
  // (disconnected).
  // They are generally placed in front of a component, e.g., an inverter, to
  // control whether the component is connected to the grid or not.
  COMPONENT_CATEGORY_RELAY = 11;

  // A precharge module.
  // Precharging involves gradually ramping up the DC voltage to prevent any
  // potential damage to sensitive electrical components like capacitors.
  // While many inverters and batteries come equipped with in-built precharging
  // mechanisms, some may lack this feature. In such cases, we need to use
  // external precharging modules.
  COMPONENT_CATEGORY_PRECHARGER = 12;

  // A fuse.
  // Fuses are used to protect electrical components from overcurrents.
  COMPONENT_CATEGORY_FUSE = 13;

  // A voltage transformer.
  // Voltage transformers are used to step up or step down the voltage, keeping
  // the power somewhat constant by increasing or decreasing the current.
  // If voltage is stepped up, current is stepped down, and vice versa.
  // Note that voltage transformers have efficiency losses, so the output power
  // is always less than the input power.
  COMPONENT_CATEGORY_VOLTAGE_TRANSFORMER = 14;

  // An HVAC (Heating, Ventilation, and Air Conditioning) system.
  COMPONENT_CATEGORY_HVAC = 15;
}

// Metadata specific to a microgrid component.
message ComponentCategoryMetadataVariant {
  oneof metadata {
    frequenz.api.common.v1.microgrid.components.Battery battery = 1;
    frequenz.api.common.v1.microgrid.components.EvCharger ev_charger = 2;
    frequenz.api.common.v1.microgrid.components.Fuse fuse = 3;
    frequenz.api.common.v1.microgrid.components.GridConnectionPoint grid = 4;
    frequenz.api.common.v1.microgrid.components.Inverter inverter = 5;
    frequenz.api.common.v1.microgrid.components.VoltageTransformer
      voltage_transformer = 6;
  }
}

// ComponentStatus defines the possible statuses for a component.
//
// !!! note
//     The status indicates the status set by the user via the user interface.
//     The status is not yet included in the Component messages and should be
//     added.
//
enum ComponentStatus {
  // The status is unspecified. This should not be used.
  COMPONENT_STATUS_UNSPECIFIED = 0;

  // The component is active.
  COMPONENT_STATUS_ACTIVE = 1;

  // The component is inactive.
  COMPONENT_STATUS_INACTIVE = 2;
}

// Microgrid electrical component details.
message Component {
  // The component ID.
  uint64 id = 1;

  // Unique identifier of the parent microgrid_id.
  uint64 microgrid_id = 2;

  // The component name.
  string name = 3;

  // The component category. E.g., Inverter, Battery, etc.
  ComponentCategory category = 4;

  // The metadata specific to the component category type.
  ComponentCategoryMetadataVariant category_type = 5;

  // The component manufacturer.
  string manufacturer = 6;

  // The model name of the component.
  string model_name = 7;

  // The status of the component.
  ComponentStatus status = 8;

  // The operational lifetime of the component.
  frequenz.api.common.v1.microgrid.Lifetime operational_lifetime = 9;

  // List of rated bounds present for the component identified by Metric.
  repeated MetricConfigBounds metric_config_bounds = 10;
}

// MetricConfigBounds describes a set of limits for a specific metric consisting
// of a lower and upper bound for said metric.
//
// This can be used for example to specify an allowed range of power output
// for a component.
message MetricConfigBounds {
  // Metric type the config bounds are for
  frequenz.api.common.v1.metrics.Metric metric = 1;

  // The set of bounds for the specified metric.
  //
  // This contains the lower and upper bounds for said metric.
  // Sources these may be derived from include the component configuration,
  // manufacturers limits, and limits of other devices.
  frequenz.api.common.v1.metrics.Bounds config_bounds = 2;
}

// ComponentConnection describes a single electrical link between two components
// within a microgrid, effectively representing the physical wiring as viewed
// from the grid connection point, if one exists, or from the islanding point,
// in case of an islanded microgrids.
//
// !!! note "Physical Representation"
//     This message is not about data flow but rather about the physical
//     electrical connections between components. Therefore, the IDs for the
//     source and destination components correspond to the actual setup within
//     the microgrid.
//
// !!! note "Direction"
//     The direction of the connection follows the flow of current away from the
//     grid connection point, or in case of islands, away from the islanding
//     point. This direction is aligned with positive current according to the
//     [Passive Sign Convention]
//     (https://en.wikipedia.org/wiki/Passive_sign_convention).
//
// !!! info "Historical Data"
//     The timestamps of when a connection was created and terminated allows for
//     tracking the changes over time to a microgrid, providing insights into
//     when and how the microgrid infrastructure has been modified.
//
message ComponentConnection {
  // Unique identifier of the component where the connection originates. This is
  // aligned with the direction of current flow away from the grid connection
  // point, or in case of islands, away from the islanding point.
  uint64 source_component_id = 1;

  // Unique ID of the component where the connection terminates. This is the
  // component towards which the current flows.
  uint64 destination_component_id = 2;

  // The operational lifetime of the connection.
  frequenz.api.common.v1.microgrid.Lifetime operational_lifetime = 3;
}

// ComponentData message aggregates multiple metrics, operational states, and
// errors, related to a specific microgrid component.
//
// !!! example
//   Example output of a component data message:
//   ```
//    {
//      component_id: 13,
//      metric_samples: [
//        /* list of metrics for multiple timestamps */
//        {
//          sampled_at: "2023-10-01T00:00:00Z",
//          metric: "DC_VOLTAGE_V",
//          value: {},
//          bounds: {},
//        },
//        {
//          sampled_at: "2023-10-01T00:00:00Z",
//          metric: "DC_VOLTAGE_V",
//          value: {},
//          bounds: {},
//        }
//      ],
//      states: [
//        /* list of states for multiple timestamps */
//        {
//          sampled_at: "2023-10-01T00:00:00Z",
//          states: [],
//          warnings: [],
//          errors: [],
//        },
//        {
//          sampled_at: "2023-10-01T00:00:00Z",
//          states: [],
//          warnings: [],
//          errors: [],
//        },
//      ]
//    }
//  ```
message ComponentData {
  // The ID of the microgrid component.
  uint64 component_id = 1;

  // List of measurements for a metric of the specific microgrid component.
  repeated frequenz.api.common.v1.metrics.MetricSample metric_samples = 2;

  // List of states of a specific microgrid component.
  repeated ComponentState states = 3;
}

// Enum to represent the various states that a component can be in.
// This enum is unified across all component categories for consistency.
enum ComponentStateCode {
  // Default value when the component state is not explicitly set.
  // This is the zero value of the enum.
  COMPONENT_STATE_CODE_UNSPECIFIED = 0;

  // State when the component is in an unknown or undefined condition.
  // This is used when the sender is unable to classify the component into any
  // other state.
  COMPONENT_STATE_CODE_UNKNOWN = 1;

  // State when the component is temporarily unavailable for operation.
  COMPONENT_STATE_CODE_UNAVAILABLE = 2;

  // State when the component is in the process of switching off.
  COMPONENT_STATE_CODE_SWITCHING_OFF = 3;

  // State when the component has successfully switched off.
  COMPONENT_STATE_CODE_OFF = 4;

  // State when the component is in the process of switching on from an off
  // state.
  COMPONENT_STATE_CODE_SWITCHING_ON = 5;

  // State when the component is in standby mode, and not immediately ready for
  // immediate operations.
  COMPONENT_STATE_CODE_STANDBY = 6;

  // State when the component is fully operational and ready for use.
  COMPONENT_STATE_CODE_READY = 7;

  // State when the component is actively consuming energy.
  COMPONENT_STATE_CODE_CHARGING = 8;

  // State when the component is actively producing or releasing energy.
  COMPONENT_STATE_CODE_DISCHARGING = 9;

  // State when the component is in an error state and may need attention.
  COMPONENT_STATE_CODE_ERROR = 10;

  // The Electric Vehicle (EV) charging cable is unplugged from the charging
  // station.
  COMPONENT_STATE_CODE_EV_CHARGING_CABLE_UNPLUGGED = 20;

  // The EV charging cable is plugged into the charging station.
  COMPONENT_STATE_CODE_EV_CHARGING_CABLE_PLUGGED_AT_STATION = 21;

  // The EV charging cable is plugged into the vehicle.
  COMPONENT_STATE_CODE_EV_CHARGING_CABLE_PLUGGED_AT_EV = 22;

  // The EV charging cable is locked at the charging station end, indicating
  // readiness for charging.
  COMPONENT_STATE_CODE_EV_CHARGING_CABLE_LOCKED_AT_STATION = 23;

  // The EV charging cable is locked at the vehicle end, indicating that
  // charging is active.
  COMPONENT_STATE_CODE_EV_CHARGING_CABLE_LOCKED_AT_EV = 24;

  // The relay is in an open state, meaning no current can flow through.
  COMPONENT_STATE_CODE_RELAY_OPEN = 30;

  // The relay is in a closed state, allowing current to flow.
  COMPONENT_STATE_CODE_RELAY_CLOSED = 31;

  // The precharger circuit is open, meaning it's not currently active.
  COMPONENT_STATE_CODE_PRECHARGER_OPEN = 40;

  // The precharger is in a precharging state, preparing the main circuit for
  // activation.
  COMPONENT_STATE_CODE_PRECHARGER_PRECHARGING = 41;

  // The precharger circuit is closed, allowing full current to flow to the main
  // circuit.
  COMPONENT_STATE_CODE_PRECHARGER_CLOSED = 42;
}

// A representation of all possible errors that can occur across all component
// categories.
enum ComponentErrorCode {
  // Default value. No specific error is specified.
  COMPONENT_ERROR_CODE_UNSPECIFIED = 0;

  // The component is reporting an unknown or an undefined error, and the sender
  // cannot parse the component error to any of the variants below.
  COMPONENT_ERROR_CODE_UNKNOWN = 1;

  // Error indicating that the component could not be switched on.
  COMPONENT_ERROR_CODE_SWITCH_ON_FAULT = 2;

  // Error indicating that the component is operating under the minimum rated
  // voltage.
  COMPONENT_ERROR_CODE_UNDERVOLTAGE = 3;

  // Error indicating that the component is operating over the maximum rated
  //  voltage.
  COMPONENT_ERROR_CODE_OVERVOLTAGE = 4;

  // Error indicating that the component is drawing more current than the
  // maximum rated value.
  COMPONENT_ERROR_CODE_OVERCURRENT = 5;

  // Error indicating that the component's consumption current is over the
  // maximum rated value during charging.
  COMPONENT_ERROR_CODE_OVERCURRENT_CHARGING = 6;

  // Error indicating that the component's production current is over the
  // maximum rated value during discharging.
  COMPONENT_ERROR_CODE_OVERCURRENT_DISCHARGING = 7;

  // Error indicating that the component is operating over the maximum rated
  // temperature.
  COMPONENT_ERROR_CODE_OVERTEMPERATURE = 8;

  // Error indicating that the component is operating under the minimum rated
  // temperature.
  COMPONENT_ERROR_CODE_UNDERTEMPERATURE = 9;

  // Error indicating that the component is exposed to high humidity levels over
  // the maximum rated value.
  COMPONENT_ERROR_CODE_HIGH_HUMIDITY = 10;

  // Error indicating that the component's fuse has blown.
  COMPONENT_ERROR_CODE_FUSE_ERROR = 11;

  // Error indicating that the component's precharge unit has failed.
  COMPONENT_ERROR_CODE_PRECHARGE_ERROR = 12;

  // Error indicating plausibility issues within the system involving this
  // component.
  COMPONENT_ERROR_CODE_PLAUSIBILITY_ERROR = 13;

  // Error indicating system shutdown due to undervoltage involving this
  // component.
  COMPONENT_ERROR_CODE_UNDERVOLTAGE_SHUTDOWN = 14;

  // Error indicating unexpected pilot failure in an electric vehicle (EV)
  // component.
  COMPONENT_ERROR_CODE_EV_UNEXPECTED_PILOT_FAILURE = 15;

  // Error indicating fault current detected in the component.
  COMPONENT_ERROR_CODE_FAULT_CURRENT = 16;

  // Error indicating a short circuit detected in the component.
  COMPONENT_ERROR_CODE_SHORT_CIRCUIT = 17;

  // Error indicating a configuration error related to the component.
  COMPONENT_ERROR_CODE_CONFIG_ERROR = 18;

  // Error indicating an illegal state requested for the component.
  COMPONENT_ERROR_CODE_ILLEGAL_COMPONENT_STATE_CODE_REQUESTED = 19;

  // Error indicating that the hardware of the component is inaccessible.
  COMPONENT_ERROR_CODE_HARDWARE_INACCESSIBLE = 20;

  // Error indicating an internal error within the component.
  COMPONENT_ERROR_CODE_INTERNAL = 21;

  // Error indicating that the component is unauthorized to perform the
  // last requested action.
  COMPONENT_ERROR_CODE_UNAUTHORIZED = 22;

  // Error indicating electric vehicle (EV) cable was abruptly unplugged from
  // the charging station.
  COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_UNPLUGGED_FROM_STATION = 40;

  // Error indicating electric vehicle (EV) cable was abruptly unplugged from
  // the vehicle.
  COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_UNPLUGGED_FROM_EV = 41;

  // Error indicating electric vehicle (EV) cable lock failure.
  COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_LOCK_FAILED = 42;

  // Error indicating an invalid electric vehicle (EV) cable.
  COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_INVALID = 43;

  // Error indicating an incompatible electric vehicle (EV) plug.
  COMPONENT_ERROR_CODE_EV_CONSUMER_INCOMPATIBLE = 44;

  // Error indicating a battery system imbalance.
  COMPONENT_ERROR_CODE_BATTERY_IMBALANCE = 50;

  // Error indicating a low state of health (SOH) detected in the battery.
  COMPONENT_ERROR_CODE_BATTERY_LOW_SOH = 51;

  // Error indicating a battery block error.
  COMPONENT_ERROR_CODE_BATTERY_BLOCK_ERROR = 52;

  // Error indicating a battery controller error.
  COMPONENT_ERROR_CODE_BATTERY_CONTROLLER_ERROR = 53;

  // Error indicating a battery relay error.
  COMPONENT_ERROR_CODE_BATTERY_RELAY_ERROR = 54;

  // Error indicating that battery calibration is needed.
  COMPONENT_ERROR_CODE_BATTERY_CALIBRATION_NEEDED = 56;

  // Error indicating that the relays have been cycled for the maximum number of
  // times.
  COMPONENT_ERROR_CODE_RELAY_CYCLE_LIMIT_REACHED = 60;
}

// Representation of a component state and errors.
message ComponentState {
  // The time at which the state was sampled.
  google.protobuf.Timestamp sampled_at = 1;

  // List of states of the microgrid component.
  //
  // !!! note
  //    The list will contain unique members. No state will exist twice in
  //    this list.
  repeated ComponentStateCode states = 2;

  // List of warnings for the microgrid component.
  //
  // !!! note
  //    This list may have warnings even if the component state is not in an
  //    error state.
  //
  // !!! note
  //    The list will contain unique members. No warning will exist twice in
  //    this list.
  repeated ComponentErrorCode warnings = 3;

  // List of errors for the microgrid component.
  //
  // !!! note
  //    This list is expected to have errors if and only if the component is in
  //    an error state.
  //
  // !!! note
  //    The list will contain unique members. No error will exist twice in
  //    this list.
  repeated ComponentErrorCode errors = 4;
}
