/* SPDX-License-Identifier: BSD-3-Clause */
/*
 * Copyright 2009 Raritan Inc. All rights reserved.
 */

#ifndef __PDUMODEL_OUTLET_IDL__
#define __PDUMODEL_OUTLET_IDL__

#include <Nameplate.idl>
#include <NumericSensor.idl>
#include <StateSensor.idl>
#include <Pole.idl>
#include <Inlet.idl>
#include <OverCurrentProtector.idl>
#include <Controller.idl>
#include <Waveform.idl>

/**
 * PDU Model
 */
module pdumodel {

    /** %Outlet statistics */
    structure OutletStatistic {
        int relayCycleCnt;                      ///< Relay switch count
        int relayFailCnt;                       ///< Relay failure count
    };

    /** %Outlet interface */
    interface Outlet_3_0_1 extends EDevice_1_0_1 {

        constant int ERR_OUTLET_NOT_SWITCHABLE = 1; ///< Outlet is not switchable
        constant int ERR_LOAD_SHEDDING_ACTIVE  = 2; ///< Load-shedding is enabled (deprecated)
        constant int ERR_OUTLET_DISABLED       = 3; ///< Outlet is disabled
        constant int ERR_OUTLET_NOT_OFF        = 4; ///< Outlet is on or in power-cylce; unstick not possible

        constant int ERR_INVALID_PARAM         = 1; ///< Invalid parameters

        /** %Outlet metadata */
        structure MetaData {
            string label;                       ///< %Outlet label
            string receptacleType;              ///< Receptacle type
            Nameplate_2_0_0 namePlate;          ///< %Nameplate information
            Rating_2_0_0 rating;                ///< Numerical usage ratings
            boolean isSwitchable;               ///< \c true if the outlet is switchable
            boolean isLatching;                 ///< \c true if the outlet is able to keep its state after power loss
            int maxRelayCycleCnt;               ///< Maximum relay cycle count
            boolean hasWaveformSupport;         ///< Whether waveform reading is supported on this outlet
        };

        /** %Outlet power state. Used both for switching and representing the current state */
        enumeration PowerState {
            PS_OFF,                             ///< Switch off / Power is off
            PS_ON                               ///< Switch on / Power is on
        };

        /** %Outlet LED state */
        [deprecated]
        structure LedState {
            boolean red;                        ///< \c true if the red LED is enabled
            boolean green;                      ///< \c true if the green LED is enabled
            boolean blinking;                   ///< \c true if the LED is blinking
        };

        /** %Outlet state */
        structure State {
            boolean available;                  ///< powerState is available
            PowerState powerState;              ///< Current power state of outlet
                                                ///< (represented by the control state of the relay, which
                                                ///<  was set by the last command sent to it)
            boolean switchOnInProgress;         ///< \c true if the outlet is pending to be switched on
                                                ///< after the sequencing delay has passed.
            boolean cycleInProgress;            ///< \c if a power-cycle is in progress. The outlet will
                                                ///< be switched on after the cycle delay has passed.
            boolean isLoadShed;                 ///< \c true if the outlet is currently switched off due
                                                ///< to being non-critical and load shedding being active
            boolean isSuspended;                ///< Whether the outlet was turned off automatically due to
                                                ///< being suspected to have caused an OCP trip event
            boolean hasInrushWaveform;          ///< Whether a valid waveform of last switch-on operation
                                                ///< can be read using {@link #getInrushWaveform()}.
            LedState ledState;                  ///< LED state (deprecated and always sent as 'off')
            time lastPowerStateChange;          ///< Time of last power state change (UNIX timestamp, UTC)
        };

        /** %Outlet power state on device startup */
        enumeration StartupState {
            SS_ON,                              ///< %Outlet will be switched on
            SS_OFF,                             ///< %Outlet will be switched off
            SS_LASTKNOWN,                       ///< Last known power state will be restored
            SS_PDUDEF                           ///< Use default state as defined in PDU settings
        };

        /** %Outlet settings */
        structure Settings {
            string name;                        ///< User-defined name
            StartupState startupState;          ///< Power state after power is applied to the outlet
            boolean usePduCycleDelay;           ///< \c true to use power-cycle delay as defined in PDU settings
            int cycleDelay;                     ///< %Outlet-specific power-cycle delay
            boolean nonCritical;                ///< \c true if outlet is non-critical (for load shedding)
            int sequenceDelay;                  ///< Delay in ms after this outlet when switching multiple outlets on
        };

        /** %Outlet sensors */
        structure Sensors {
            sensors.NumericSensor_4_0_6 voltage;                ///< RMS voltage sensor (may be a VoltageMonitoringSensor)
            sensors.NumericSensor_4_0_6 current;                ///< RMS current sensor
            sensors.NumericSensor_4_0_6 peakCurrent;            ///< Peak current sensor
            sensors.NumericSensor_4_0_6 maximumCurrent; ///< Maximum current sensor
            sensors.NumericSensor_4_0_6 unbalancedCurrent;      ///< Current unbalance sensor
            sensors.NumericSensor_4_0_6 activePower;            ///< Active power sensor
            sensors.NumericSensor_4_0_6 reactivePower;          ///< Reactive power sensor
            sensors.NumericSensor_4_0_6 apparentPower;  ///< Apparent power sensor
            sensors.NumericSensor_4_0_6 powerFactor;            ///< Power factor sensor
            sensors.NumericSensor_4_0_6 displacementPowerFactor;///< Displacement power factor sensor
            sensors.NumericSensor_4_0_6 activeEnergy;           ///< Active energy sensor
            sensors.NumericSensor_4_0_6 apparentEnergy; ///< Apparent energy sensor
            sensors.NumericSensor_4_0_6 phaseAngle;     ///< Phase angle sensor
            sensors.NumericSensor_4_0_6 lineFrequency;  ///< AC line frequency sensor
            sensors.NumericSensor_4_0_6 crestFactor;        ///< Crest factor sensor
            sensors.NumericSensor_4_0_6 voltageThd;             ///< Voltage total harmonic distortion sensor
            sensors.NumericSensor_4_0_6 currentThd;             ///< Current total harmonic distortion sensor
            sensors.NumericSensor_4_0_6 inrushCurrent;          ///< In-rush current occuring after turning outlet on
            sensors.StateSensor_4_0_5   outletState;            ///< %Outlet power state sensor
        };

        /** Event: Power control was initiated */
        valueobject PowerControlEvent extends event.UserEvent {
            PowerState state;                   ///< State the outlet was switched to (if cycle is false)
            boolean cycle;                      ///< Whether the outlet was cycled
        };

        /** Event: Outlet state has changed */
        valueobject StateChangedEvent extends idl.Event {
            State oldState;                     ///< State before change
            State newState;                     ///< State after change
        };

        /** Event: Outlet settings have been changed */
        valueobject SettingsChangedEvent extends event.UserEvent {
            Settings oldSettings;               ///< Settings before change
            Settings newSettings;               ///< Settings after change
        };

        /**
         * Retrieve the outlet metadata.
         *
         * @return %Outlet metadata
         */
        MetaData getMetaData();

        /**
         * Get the outlet sensors.
         *
         * @return %Outlet sensors
         */
        Sensors getSensors();

        /**
         * Retrieve the outlet state.
         *
         * @return %Outlet state
         */
        State getState();

        /**
         * Switch the outlet.
         *
         * @param pstate  New power state
         *
         * @return 0 if OK
         * @return 1 if the outlet is not switchable
         * @return 3 if the outlet is disabled
         */
        int setPowerState(in PowerState pstate);

        /**
         * Power-cycle the outlet.
         *
         * @return 0 if OK
         * @return 1 if the outlet is not switchable
         * @return 3 if the outlet is disabled
         */
        int cyclePowerState();

        /**
         * Retrieve the outlet settings.
         *
         * @return %Outlet settings
         */
        Settings getSettings();

        /**
         * Change the outlet settings.
         *
         * @param settings  New outlet settings
         *
         * @return 0 if OK
         * @return 1 if any parameters are invalid
         */
        int setSettings(in Settings settings);

        /**
         * Get inlet, overcurrent protector and poles.
         *
         * @param i  Result: %Inlet reference
         * @param o  Result: Overcurrent protector reference
         * @param p  Result: List of poles
         */
        void getIOP(out Inlet_3_0_1 i, out OverCurrentProtector_4_0_1 o, out vector<Pole_9_0_0> p);

        /**
         * Get the controller for this outlet.
         *
         * @return Sub controller reference
         */
        Controller_5_0_0 getController();

        /**
         * Get the voltage and current waveforms at the time of last switch on operation.
         *
         * @note If waveform reading is not supported or a waveform could not be acquired for other
         *       reasons (e.g. the outlet not actually be switchable, or the outlet board being reset
         *       since the outlet was turned on), an empty waveform is returned.
         *
         * @return Waveform samples
         */
        Waveform getInrushWaveform();

        /**
         * Trigger an attempt to un-stick sticking relay contacts
         *
         * Warning: Please contact Tech Support before using this.
         *
         * Tries repairing relay contacts that are sticked together due to wear
         * by switching the relay in a certain pattern.
         * Prior to running this method, the outlet must be in 'off' state
         * to acknowledge that loads were disconnected.
         *
         * @return 0 if unsticking was triggered successfully
         * @return 1 if outlet is not switchable
         * @return 3 if the outlet is disabled
         * @return 4 if relay is in a power cycle or on
         */
        int unstick();
    };

}

#endif
