import time
import importlib
from datetime import datetime
from itertools import count
from pvp.alarm import AlarmType, AlarmSeverity
[docs]class Alarm:
"""
Representation of alarm status and parameters
Parameterized by a :class:`Alarm_Rule` and managed by :class:`Alarm_Manager`
"""
id_counter = count()
"""
:class:`itertools.count`: used to generate unique IDs for each alarm
"""
[docs] def __init__(self,
alarm_type: AlarmType,
severity: AlarmSeverity,
start_time: float = None,
latch: bool = True,
cause: list = None,
value=None,
message=None):
"""
Args:
alarm_type ( :class:`.AlarmType` ): Type of alarm
severity ( :class:`.AlarmSeverity` ) : Severity of alarm
start_time (float): Timestamp of alarm start, (as generated by ``time.time()``
cause (ValueName): The :class:`.ValueName` that caused the alarm to be fired
value (int, float): optional - numerical value that generated the alarm
message (str): optional - override default text generated by :class:`~pvp.gui.alarm_manager.AlarmManager`
Attributes:
id (int): unique alarm ID
end_time (None, float): If None, alarm has not ended. otherwise timestamp
active (bool): Whether or not the alarm is currently active
"""
self.id = next(Alarm.id_counter) # type: int
assert isinstance(severity, AlarmSeverity)
self._severity = severity
assert isinstance(alarm_type, AlarmType)
self._alarm_type = alarm_type
if start_time is None:
self.start_time = time.time()
else:
assert isinstance(start_time, float)
self.start_time = start_time
self.active = True
if self.severity == AlarmSeverity.OFF:
self.active = False
self.end_time = None
self.value = value
self.message = message
self.latch = latch
self.cause = cause
# if not managed:
# self.manager.register_alarm(self)
@property
def severity(self) -> AlarmSeverity:
"""
Alarm Severity, property without setter to prevent change after instantiation
Returns:
:class:`.AlarmSeverity`
"""
# no setter, don't want to be able to change after instantiation
return self._severity
@property
def alarm_type(self) -> AlarmType:
"""
Alarm Type, property without setter to prevent change after instantiation
Returns:
:class:`.AlarmType`
"""
return self._alarm_type
[docs] def deactivate(self):
"""
If active, register an end time and set as ``active == False``
Returns:
"""
if not self.active: # pragma: no cover
return
self.end_time = time.time()
self.active = False
# make sure the manager deactivates us.
# manager checks if this has already been done so doesn't recurse
#self.manager.deactivate_alarm(self)
def __str__(self) -> str:
"""
Loggable representation of alarm
Returns:
str
"""
if self.end_time is None:
end_time = ""
else:
end_time = datetime.fromtimestamp(self.end_time).isoformat()
alarm_str = "ALARM: {id} - {name} - SEVERITY: {severity} - START_TIME: {start_time} - END_TIME: {end_time}".format(
id = self.id,
name = self.alarm_type.name,
start_time = datetime.fromtimestamp(self.start_time).isoformat(),
end_time = end_time,
severity = self.severity.name
)
return alarm_str