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

#ifndef __PDUMODEL_TRANSFERSWITCH_IDL__
#define __PDUMODEL_TRANSFERSWITCH_IDL__

#include <EDevice.idl>
#include <Nameplate.idl>
#include <Pole.idl>
#include <StateSensor.idl>
#include <TransferSwitchBypassStateSensor.idl>
#include <Waveform.idl>

/**
 * PDU Model
 */
module pdumodel {

    /** Transfer switch interface */
    interface TransferSwitch_6_0_1 extends EDevice_1_0_1 {

        constant int ERR_INVALID_PARAM    = 1; ///< Invalid parameters
        constant int ERR_SWITCH_PREVENTED = 2; ///< Switching failed due to an alarm that may be overridden
        constant int ERR_SWITCH_FAILED    = 3; ///< Switching failed, no override possible

        /** Transfer switch type */
        enumeration Type {
            STS,                        ///< Static transfer switch (using SCRs as switch technology)
            ATS,                        ///< Asynchronous transfer switch (using relays)
            HTS                         ///< Hybrid transfer switch (relays plus SCRs)
        };

        [unknown_fallback("REASON_UNKNOWN")]
        enumeration TransferReason {
            REASON_UNKNOWN,             ///< Transfer reason unknown
            REASON_STARTUP,             ///< Startup or return to normal conditions
            REASON_MANUAL_TRANSFER,     ///< Manual transfer
            REASON_AUTO_RETRANSFER,     ///< Automatic retransfer
            REASON_POWER_FAILURE,       ///< Previous inlet power failed
            REASON_POWER_QUALITY,       ///< New inlet provided better power quality
            REASON_OVERLOAD,            ///< Switched off due to overload alarm
            REASON_OVERHEAT,            ///< Switched off due to overheat alarm
            REASON_INTERNAL_FAILURE,    ///< Transferred because of hardware failure (e.g. switch fault)
            REASON_BYPASS_ACTIVE        ///< Switched off due to active bypass
        };

        /** Transfer switch metadata */
        structure MetaData {
            string label;               ///< Transfer switch label
            Nameplate_2_0_0 namePlate;  ///< %Nameplate information
            Rating_2_0_0 rating;        ///< Numerical usage ratings
            Type type;                  ///< Transfer switch type
            int sourceCount;            ///< Number of sources
        };

        /* Values for operational state sensor */
        constant int OPERATIONAL_STATE_OFF = 0;                 ///< Both inlets are off
        constant int OPERATIONAL_STATE_NORMAL = 1;              ///< Active inlet equals preferred inlet
        constant int OPERATIONAL_STATE_STANDBY = 2;             ///< Active inlet and preferred inlet are different
        constant int OPERATIONAL_STATE_NON_REDUNDANT = 3;       ///< Active inlet equals preferred inlet, standby power critical
        constant int OPERATIONAL_STATE_BYPASSED = 4;            ///< Both inlets are off, but bypass is active

        /* Bitmask values for switch fault sensors */
        constant int SWITCH_FAULT_I1_SHORT = 1;                 ///< Inlet 1 switch is permanently closed
        constant int SWITCH_FAULT_I1_OPEN = 2;                  ///< Inlet 1 switch is permanently open
        constant int SWITCH_FAULT_I2_SHORT = 4;                 ///< Inlet 2 switch is permanently closed
        constant int SWITCH_FAULT_I2_OPEN = 8;                  ///< Inlet 2 switch is permanently open

        /** Transfer switch sensors */
        structure Sensors {
            sensors.StateSensor_4_0_7 selectedSource;           ///< Selected source sensor
            sensors.StateSensor_4_0_7 operationalState;         ///< Operational state sensor (off, normal, standby)
            sensors.NumericSensor_4_0_8 sourceVoltagePhaseSyncAngle;
                                                                ///< Maximum phase difference between two sources
            sensors.StateSensor_4_0_7 overloadAlarm;            ///< Overload alarm
            sensors.StateSensor_4_0_7 phaseSyncAlarm;           ///< Source phases out of sync
            sensors.StateSensor_4_0_7 switchFault;              ///< Switch fault (ok, open, short)
            sensors.StateSensor_4_0_7 installFaultAlarm;        ///< Install fault alarm
            sensors.StateSensor_4_0_7 outputStatus;             ///< Output voltage status (ok, fault)
            TransferSwitchBypassStateSensor bypassState;
        };

        /** Transfer switch settings */
        [sparse_in]
        structure Settings {
            string name;                        ///< User-defined name

            int preferredSource;                ///< Preferred inlet
            boolean autoRetransfer;             ///< Enable automatic retransfer if power on active inlet is restored
            boolean noAutoRetransferIfPhaseFault; ///< Don't automatically retransfer if inlet phases are out of sync
            int autoRetransferWaitTime;         ///< Time (in s) to delay retransfer after power restoration
            boolean manualTransferEnabled;      ///< Enable state of 'manual transfer' front panel button
            boolean phaseSyncSensorEnabled;     ///< False to force the 'phaseSyncAlarm' sensor to unavailable
        };

        /** Transfer switch statistics */
        structure Statistics {
            int transferCount;                  ///< Number of transfers since device startup
            int powerFailDetectTime;            ///< Detection time in us for the last inlet power failure
            int relayOpenTime;                  ///< Time in us until all relays have opened during the last transfer
            int totalTransferTime;              ///< Total time in us for last transfer
        };

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

        /**
         * Retrieve the transfer switch metadata.
         *
         * @return Transfer switch metadata
         */
        MetaData getMetaData();

        /**
         * Get the transfer switch sensors.
         *
         * @return Transfer switch sensors
         */
        Sensors getSensors();

        /**
         * Get the list of transfer switch poles.
         *
         * @return List of poles
         */
        vector<ThrowPole_3_0_0> getPoles();

        /**
         * Retrieve the transfer switch settings.
         *
         * @return Transfer switch settings
         */
        Settings getSettings();

        /**
         * Change the transfer switch settings.
         *
         * @return 0 if OK
         * @return 1 if any parameters are invalid
         *
         * @note The Settings structure can be "sparse"; fields missing in the
         *       JSON representation will remain unchanged.
         */
        int setSettings(in Settings settings);

        /**
         * Retrieve the transfer switch statistics.
         *
         * @return Transfer switch statistics
         */
        Statistics getStatistics();

        /**
         * Select the active inlet. If the new inlet is available,
         * it will become both active and preferred.
         *
         * @param source         New active inlet index
         * @param faultOverride  Force switch even if the phase sync angle
         *                       between the inputs is too large
         *
         * @return 0 if OK
         * @return ERR_INVALID_PARAM if the selected source is invalid
         * @return ERR_SWITCH_PREVENTED if switching failed due to an alarm that may be overridden
         * @return ERR_SWITCH_FAILED if switching failed and no override is possible
         */
        int transferToSource(in int source, in boolean faultOverride);

        /**
         * Get the reason for the last transfer.
         *
         * @return Last transfer reason
         */
        TransferReason getLastTransferReason();

        /**
         * Get the voltage and current waveforms during the last transfer.
         *
         * @return Waveform samples
         */
        Waveform getLastTransferWaveform();

        /** Transfer log entry */
        structure TransferLogEntry {
            time timestamp;                     ///< Time of the transfer (UNIX timestamp, UTC)
            int oldInlet;                       ///< Active inlet before transfer (0 for none)
            int newInlet;                       ///< Active inlet after transfer (0 for none)
            TransferReason reason;              ///< Transfer reason
            Waveform waveform;                  ///< Voltage and current waveforms
            Statistics statistics;              ///< Transfer statistics
            int switchFault;                    ///< Switch fault status
        };

        /**
         * Retrieve the transfer log.
         *
         * @return Transfer log
         */
        vector<TransferLogEntry> getTransferLog();

        /**
         * Transfer switch parameter map.
         *
         * The set of parameters, their meaning and allowed set of values are
         * technology-dependent and subject to change. Do not modify any values
         * without instruction from Raritan!
         */
        typedef map<string, int> Parameters;

        /**
         * Retrieve the transfer switch parameters.
         *
         * @return Parameters map
         */
        Parameters getParameters();

        /**
         * Update one or more transfer switch parameters.
         *
         * @param parameters  Map of transfer switch parameters. Parameters
         *                    which are not in the map remain unchanged.
         *
         * @return 0 if OK
         * @return ERR_INVALID_PARAM if any parameter is invalid
         */
        int setParameters(in Parameters parameters);

    };

}

#endif
