syntax = "proto3";

option go_package = "github.com/opencord/device-management-interface/v3/go/dmi";
package dmi;

import "google/protobuf/timestamp.proto";

// The model used to represent a HW is based on RFC8348 (https://tools.ietf.org/html/rfc8348)

message Uuid {
    string uuid = 1;
}

message HardwareID {
    Uuid uuid = 1;
}

message Uri {
    string uri = 1;
}

enum ComponentType {
    COMPONENT_TYPE_UNDEFINED = 0;
    COMPONENT_TYPE_UNKNOWN = 1;
    COMPONENT_TYPE_CHASSIS = 2;
    COMPONENT_TYPE_BACKPLANE = 3;
    COMPONENT_TYPE_CONTAINER = 4;
    COMPONENT_TYPE_POWER_SUPPLY = 5;
    COMPONENT_TYPE_FAN = 6;
    COMPONENT_TYPE_SENSOR = 7;
    COMPONENT_TYPE_MODULE = 8;
    COMPONENT_TYPE_PORT = 9;
    COMPONENT_TYPE_CPU = 10;
    COMPONENT_TYPE_BATTERY = 11;
    COMPONENT_TYPE_STORAGE = 12;
    COMPONENT_TYPE_MEMORY = 13;
    // A component of type "TRANSCEIVER" could have 0 or more components of type "PORT" as children.
    COMPONENT_TYPE_TRANSCEIVER = 14;
}

enum ComponentAdminState {
    COMP_ADMIN_STATE_UNDEFINED = 0;
    COMP_ADMIN_STATE_UNKNOWN = 1;
    COMP_ADMIN_STATE_LOCKED = 2;
    COMP_ADMIN_STATE_SHUTTING_DOWN = 3;
    COMP_ADMIN_STATE_UNLOCKED = 4;
    // Indicates that the component is in a prohibited administrative state, meaning operations are not allowed.
    // Typically used to enforce security or policy restrictions.
    COMP_ADMIN_STATE_ISOLATED = 6;    
    // Indicates that the component is administratively isolated from the rest of the system.
    // Used when a component must be separated for maintenance, troubleshooting, or security reasons.
    COMP_ADMIN_STATE_PROHIBITED = 5;
}

enum ComponentOperState {
    COMP_OPER_STATE_UNDEFINED = 0;
    COMP_OPER_STATE_UNKNOWN = 1;
    COMP_OPER_STATE_DISABLED = 2;
    COMP_OPER_STATE_ENABLED = 3;
    COMP_OPER_STATE_TESTING = 4;
    // Indicates that the component is operating normally.
    COMP_OPER_STATE_NORMAL = 5;
    // Indicates that the component is currently being configured.
    COMP_OPER_STATE_CONFIGURING = 6;
    // Indicates that the component is automatically loading configuration or software.
    COMP_OPER_STATE_AUTOMATIC_LOADING = 7;
    // Indicates that the component has encountered a failure.
    COMP_OPER_STATE_FAILED = 8;
    // Indicates that the component is temporarily shut down.
    // The component is in a high temperature shutdown state due to exceeding safe operating temperature limits.
    COMP_OPER_STATE_HIGH_TEMP_SHUTDOWN= 9;
    // Indicates that the component is manually shut down.
    COMP_OPER_STATE_MANUAL_SHUTDOWN = 10;
    // Indicates that the component is shut down to save power.
    COMP_OPER_STATE_POWER_SAVING_SHUTDOWN = 11;
    // Indicates that the component's type does not match the expected type.
    COMP_OPER_STATE_TYPE_MISMATCH = 12;  
}

enum ComponentUsageState {
    COMP_USAGE_STATE_UNDEFINED = 0;
    COMP_USAGE_STATE_UNKNOWN = 1;
    COMP_USAGE_STATE_IDLE = 2;
    COMP_USAGE_STATE_ACTIVE = 3;
    COMP_USAGE_STATE_BUSY = 4;
}

enum ComponentAlarmState {
    COMP_ALARM_STATE_UNDEFINED = 0;
    COMP_ALARM_STATE_UNKNOWN = 1;
    COMP_ALARM_STATE_UNDER_REPAIR= 2;
    COMP_ALARM_STATE_CRITICAL = 3;
    COMP_ALARM_STATE_MAJOR = 4;
    COMP_ALARM_STATE_MINOR = 5;
    COMP_ALARM_STATE_WARNING = 6;
    COMP_ALARM_STATE_INDETERMINATE = 7;
}

enum ComponentStandbyState {
    COMP_STANDBY_STATE_UNDEFINED = 0;
    COMP_STANDBY_STATE_UNKNOWN = 1;
    COMP_STANDBY_STATE_HOT = 2;
    COMP_STANDBY_STATE_COLD = 3;
    COMP_STANDBY_STATE_PROVIDING_SERVICE = 4;
}

message ComponentState {
    google.protobuf.Timestamp state_last_changed = 1;
    ComponentAdminState admin_state = 2;
    ComponentOperState oper_state = 3;
    ComponentUsageState usage_state = 4;
    ComponentAlarmState alarm_state = 5;
    ComponentStandbyState standby_state = 6;
}

enum DataValueType {
    VALUE_TYPE_UNDEFINED = 0;
    VALUE_TYPE_OTHER = 1;
    VALUE_TYPE_UNKNOWN = 2;
    VALUE_TYPE_VOLTS_AC = 3;
    VALUE_TYPE_VOLTS_DC = 4;
    VALUE_TYPE_AMPERES = 5;
    VALUE_TYPE_WATTS = 6;
    VALUE_TYPE_HERTZ = 7;
    VALUE_TYPE_CELSIUS = 8;
    VALUE_TYPE_PERCENT_RH = 9;
    VALUE_TYPE_RPM = 10;
    VALUE_TYPE_CMM = 11;
    VALUE_TYPE_TRUTH_VALUE = 12;
    VALUE_TYPE_PERCENT = 13;
    VALUE_TYPE_METERS = 14;
    VALUE_TYPE_BYTES = 15;
    VALUE_TYPE_DBM = 16;
}

enum ValueScale {
    VALUE_SCALE_UNDEFINED = 0;
    VALUE_SCALE_YOCTO = 1;
    VALUE_SCALE_ZEPTO = 2;
    VALUE_SCALE_ATTO = 3;
    VALUE_SCALE_FEMTO = 4;
    VALUE_SCALE_PICO = 5;
    VALUE_SCALE_NANO = 6;
    VALUE_SCALE_MICRO = 7;
    VALUE_SCALE_MILLI = 8;
    VALUE_SCALE_UNITS = 9;
    VALUE_SCALE_KILO = 10;
    VALUE_SCALE_MEGA = 11;
    VALUE_SCALE_GIGA = 12;
    VALUE_SCALE_TERA = 13;
    VALUE_SCALE_PETA = 14;
    VALUE_SCALE_EXA = 15;
    VALUE_SCALE_ZETTA = 16;
    VALUE_SCALE_YOTTA =17;
}

enum SensorStatus {
    SENSOR_STATUS_UNDEFINED = 0;
    SENSOR_STATUS_OK = 1;
    SENSOR_STATUS_UNAVAILABLE = 2;
    SENSOR_STATUS_NONOPERATIONAL = 3;
}

enum TransceiverType {
    TYPE_UNDEFINED = 0;
    ETHERNET = 1;
    GPON = 2;
    XGPON = 3;
    XGSPON = 4;
    CPON = 5;
    NG_PON2 = 6;
    EPON = 7;
    COMBO_GPON_XGSPON = 8;
    // Add more here

    TYPE_NOT_DETECTED = 255;
}

message ComponentSensorData {
    int32 value = 1;
    DataValueType type = 2;
    ValueScale scale = 3;
    int32 precision = 4;
    SensorStatus status = 5;
    string units_display = 6;
    google.protobuf.Timestamp timestamp = 7;
    uint32 value_update_rate = 8;
    // data_type can be of the string representation of MetricNames or something else as well
    string data_type = 9;
}

message PortComponentAttributes{
    enum ConnectorType {
        CONNECTOR_TYPE_UNDEFINED = 0;
        RJ45 = 1;
        FIBER_LC = 2;
        FIBER_SC_PC = 3;
        FIBER_MPO = 4;
        RS232 = 5;
    }
    enum Speed {
        SPEED_UNDEFINED = 0;
        DYNAMIC = 1;
        GIGABIT_1 = 2;
        GIGABIT_10 = 3;
        GIGABIT_25 = 4;
        GIGABIT_40 = 5;
        GIGABIT_100 = 6;
        GIGABIT_400 = 7;
        MEGABIT_2500 = 8;
        MEGABIT_1250 = 9;
    }
    enum Protocol {
        PROTOCOL_UNDEFINED = 0;
        ETHERNET = 1;
        GPON = 2;
        XGPON = 3;
        XGSPON = 4;
        GFAST = 5;
        SERIAL = 6;
        EPON = 7;
        BITS = 8;
    }
    ConnectorType connector_type = 1;
    Speed speed = 2;
    Protocol protocol = 3;
    string physical_label = 4;
    // The mapping_label can be used to map ports between the DMI interface and other systems like VOLTHA
    // The value of the mapping_label should be exactly the same as generated for the same port by the other
    // system
    string mapping_label = 5;
    PonIdConfig pon_id_config = 6;
    bool speed_autonegotiation = 7; //Only valid for ethernet type port components. True if enabled, false otherwise.
    PonDistance  distance = 8; //Pon max distance and max differential reach distance.
}

message PonDistance {
    /*
     * The ITU-T G.987.x series of Recommendations addresses the linear extent parameters of XG-PON
     * using the single concept of fibre distance. An ONU is characterized by its fibre distance, and for
     * each pair of ONUs on the same OLT PON interface, the differential fibre distance is the difference
     * between the two individual fibre distances. Each specific PMD layer parameter set contains a
     * provision to support a specific maximum fibre distance. The XG-PON TC layer specification
     * contains a provision to support specific ranges of maximum fibre distance and maximum
     * differential fibre distance. These ranges can be configurable for a given system. One can expect that
     * for each XG-PON deployment, the configured TC layer maximum fibre distance will match the
     * maximum fibre distance supported by the selected PMD layer parameter set.
    */
    uint32 max_distance = 1;  //Distance in kilometers the maximum logical distance on an ONU on the PON
    uint32 max_differential_distance = 2;  // maximum distance between the closest ONU to the farthest ONU in km.
}
message PortComponentChangeAttributes {
    PonIdConfig pon_id_config = 1;
    PonDistance  distance = 2; //Pon max distance and max differential reach distance.
}

message TransceiverComponentChangeAttributes {
    TransceiverType trans_type = 1;
}

message PonIdConfig {
    // The pon_id and pon_id_transmit_periodicity attributes are valid only for ports of type GPON, XGPON and XGSPON
    // For GPON pon_id is a 7 byte value
    // For XGS-PON, it's a 32 bit value, should be encoded in the first 4 bytes of pon_id in network byte order
    bytes pon_id = 1;
    uint32 pon_id_transmit_periodicity = 2; // The value is in seconds and defaults to 1 second
}

message ContainerComponentAttributes{
    string physical_label = 1;
}

message PsuComponentAttributes{
    enum SupportedVoltage {
        SUPPORTED_VOLTAGE_UNDEFINED = 0;
        V48 = 1;
        V230 = 2;
        V115 = 3;
    }
    SupportedVoltage supported_voltage = 1;
}

message TransceiverComponentsAttributes{
    enum FormFactor {
        FORM_FACTOR_UNKNOWN = 0;
        QSFP = 1;
        QSFP_PLUS = 2;
        QSFP28 = 3;
        SFP = 4;
        SFP_PLUS = 5;
        XFP = 6;
        CFP4 = 7;
        CFP2 = 8;
        CPAK = 9;
        X2 = 10;
        OTHER = 11;
        CFP = 12;
        CFP2_ACO = 13;
        CFP2_DCO = 14;
        QSFP_DD = 15;
    }

    FormFactor form_factor = 1;
    TransceiverType trans_type = 2;
    // The maximum reach that can be achieved by this transceiver
    uint32 max_distance = 3;
    ValueScale max_distance_scale = 4;
    // The receive and transmit wavelengths that the transeiver operates on
    repeated uint32 rx_wavelength = 5;
    repeated uint32 tx_wavelength = 6;
    ValueScale wavelength_scale = 7;
    // The tx powers on the transceiver; the value type of tx_power should be dBm.
    // Note: When there are multiple rx/tx wavelengths and powers
    // each of the corresponding ones should be aligned on the same index of the array
    repeated int32 tx_power = 8;
    ValueScale tx_power_scale = 9;

}

message Component {
    // The name of a component uniquely identifies a component within the hardware
    string name = 1;
    ComponentType class = 2;
    string description = 3;
    // The name of the parent of this component, empty string("") in case of the root component
    string parent = 4;
    int32 parent_rel_pos = 5;
    repeated Component children = 6;
    string hardware_rev = 7;
    string firmware_rev = 8;
    string software_rev = 9;
    string serial_num = 10;
    string mfg_name = 11;
    // Apart from the definition of this attribute as defined in RFC 8348, implementations could choose to carry
    // the manufacturer's part number in this attribute.
    string model_name = 12;
    string alias = 13;
    string asset_id = 14;
    bool is_fru = 15;
    google.protobuf.Timestamp mfg_date = 16;
    Uri uri = 17;
    // The uuid of the component uniquely identifies the component across the entire system
    Uuid uuid= 18;
    ComponentState state = 19;
    repeated ComponentSensorData sensor_data = 20;
    // The attribute 'specific' can be populated for components where more details are required by the users of the DMI interface
    oneof specific {
        PortComponentAttributes port_attr = 50;
        ContainerComponentAttributes container_attr = 51;
        PsuComponentAttributes psu_attr = 52;
        TransceiverComponentsAttributes transceiver_attr = 53;
    }
}

message Hardware {
    google.protobuf.Timestamp last_change = 1;
    // Each HW has one parent/root and all other components are children of this
    // The class of the root component would be set as UNDEFINED
    Component root = 2;
    // TODO: Authentication?
    // Timestamp at which the hardware last booted
    google.protobuf.Timestamp last_booted = 3;
}

// The attributes of a component which are modifiable from the client side
message ModifiableComponent {
    // The name has to be unique for each component within the hardware and implementations need to
    // ascertain this when modifying the name
    string name = 1;
    ComponentType class = 2;
    Component parent = 3;
    int32 parent_rel_pos = 4;
    string alias = 5;
    string asset_id = 6;
    Uri uri = 7;
    ComponentAdminState admin_state = 8;
    // The attribute 'specific' can be populated for specific class of components
    oneof specific {
        PortComponentChangeAttributes port_attr = 50;
        TransceiverComponentChangeAttributes trx_attr = 51;
    }
}
