Source code for sttp.metadata.record.phasor

# ******************************************************************************************************
#  metadata/record/phasor.py - Gbtc
#
#  Copyright © 2021, Grid Protection Alliance.  All Rights Reserved.
#
#  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
#  the NOTICE file distributed with this work for additional information regarding copyright ownership.
#  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this
#  file except in compliance with the License. You may obtain a copy of the License at:
#
#      http://opensource.org/licenses/MIT
#
#  Unless agreed to in writing, the subject software distributed under the License is distributed on an
#  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
#  License for the specific language governing permissions and limitations.
#
#  Code Modification History:
#  ----------------------------------------------------------------------------------------------------
#  02/09/2021 - J. Ritchie Carroll
#       Generated original version of source code.
#
# ******************************************************************************************************

from __future__ import annotations
from gsf import Empty
from typing import Optional, List, TYPE_CHECKING
from enum import IntEnum
from datetime import datetime

if TYPE_CHECKING:
    from .measurement import MeasurementRecord
    from .device import DeviceRecord

[docs] class CompositePhasorMeasurement(IntEnum): ANGLE = 0 MAGNITUDE = 1
[docs] class PhasorRecord: """ Represents a record of phasor metadata in the STTP. """ DEFAULT_TYPE = "V" DEFAULT_PHASE = "+" DEFAULT_BASEKV = 500 DEFAULT_UPDATEDON = Empty.DATETIME def __init__(self, id: int, deviceacronym: str, label: str, type: str, phase: str, sourceindex: int, basekv: int = ..., updatedon: datetime = ... ): """ Constructs a new `PhasorRecord`. """ self._id = id self._deviceacronym = deviceacronym self._label = label self._type = PhasorRecord.DEFAULT_TYPE if type is None or type == Empty.STRING else type self._phase = PhasorRecord.DEFAULT_PHASE if phase is None or phase == Empty.STRING else phase self._sourceindex = sourceindex self._basekv = PhasorRecord.DEFAULT_BASEKV if basekv is ... or basekv == 0 else basekv self._updatedon = PhasorRecord.DEFAULT_UPDATEDON if updatedon is ... else updatedon self.device: Optional[DeviceRecord] = None """ Defines the associated `DeviceRecord` for this `PhasorRecord`. """ self.measurements: List[MeasurementRecord] = [] """ Defines the two `MeasurementRecord` values, i.e., the angle and magnitude, associated with this `PhasorRecord`. """ @property def id(self) -> int: # <PhasorDetail>/<ID> """ Gets the unique integer identifier for this `PhasorRecord`. """ return self._id @property def deviceacronym(self) -> str: # <PhasorDetail>/<DeviceAcronym> """ Gets the alpha-numeric identifier of the associated device for this `PhasorRecord`. """ return self._deviceacronym @property def label(self) -> str: # <PhasorDetail>/<Label> """ Gets the free form label for this `PhasorRecord`. """ return self._label @property def type(self) -> str: # <PhasorDetail>/<Type> """ Gets the phasor type, i.e., "I" or "V", for current or voltage, respectively, for this `PhasorRecord`. """ return self._type @property def phase(self) -> str: # <PhasorDetail>/<Phase> """ Gets the phase of this `PhasorRecord`, e.g., "A", "B", "C", "+", "-", "0", etc. """ return self._phase @property def basekv(self) -> int: # <PhasorDetail>/<BaseKV> """ Gets the base, i.e., nominal, kV level for this `PhasorRecord`. """ return self._sourceindex @property def sourceindex(self) -> int: # <PhasorDetail>/<SourceIndex> """ Gets the source index, i.e., the 1-based ordering index of the phasor in its original context, for this `PhasorRecord`. """ return self._sourceindex @property def updatedon(self) -> datetime: # <PhasorDetail>/<UpdatedOn> """ Gets the `datetime` of when this `PhasorRecord` was last updated. """ return self._updatedon @property def angle_measurement(self) -> Optional[MeasurementRecord]: """ Gets the associated angle `MeasurementRecord`, or `None` if not available. """ return None if len(self.measurements) <= CompositePhasorMeasurement.ANGLE else \ self.measurements[CompositePhasorMeasurement.ANGLE] @property def magnitude_measurement(self) -> Optional[MeasurementRecord]: """ Gets the associated magnitude `MeasurementRecord`, or `None` if not available. """ return None if len(self.measurements) <= CompositePhasorMeasurement.MAGNITUDE else \ self.measurements[CompositePhasorMeasurement.MAGNITUDE]