|
| 1 | +import binascii |
1 | 2 | from itertools import islice |
2 | 3 | from typing import Any, List |
3 | 4 |
|
4 | | -from yamcs.client import YamcsClient |
| 5 | +from yamcs.client import EventAlarm, ParameterAlarm, YamcsClient |
5 | 6 |
|
6 | 7 | from yamcs.cli import utils |
7 | 8 | from yamcs.cli.completers import ProcessorCompleter |
8 | 9 |
|
9 | 10 |
|
| 11 | +def format_parameter_trip_value(alarm: ParameterAlarm): |
| 12 | + # Complicated condition to workaround a seen use case |
| 13 | + # where the alarm table contains no trigger value |
| 14 | + # (which should really not occur) |
| 15 | + if alarm._proto.parameterDetail.HasField("triggerValue"): |
| 16 | + val = alarm.trigger_value.eng_value |
| 17 | + if isinstance(val, bool): |
| 18 | + return str(val).lower() |
| 19 | + elif isinstance(val, (bytes, bytearray)): |
| 20 | + return str(binascii.hexlify(val), "ascii") |
| 21 | + else: |
| 22 | + return str(alarm.trigger_value.eng_value) |
| 23 | + else: |
| 24 | + return None |
| 25 | + |
| 26 | + |
| 27 | +def format_event_trip_value(alarm: EventAlarm): |
| 28 | + # Complicated condition to workaround a seen use case |
| 29 | + # where the alarm table contains no trigger value |
| 30 | + # (which should really not occur) |
| 31 | + if alarm._proto.eventDetail.HasField("triggerEvent"): |
| 32 | + return alarm.trigger_event.message |
| 33 | + else: |
| 34 | + return None |
| 35 | + |
| 36 | + |
10 | 37 | class AlarmsCommand(utils.Command): |
11 | 38 | def __init__(self, parent): |
12 | 39 | super(AlarmsCommand, self).__init__(parent, "alarms", "Manage alarms") |
@@ -114,15 +141,43 @@ def list_(self, args): |
114 | 141 | instance = opts.require_instance() |
115 | 142 | processor = client.get_processor(instance, args.processor) |
116 | 143 |
|
117 | | - rows: List[List[Any]] = [["TIME", "NAME", "SEQNO", "SEVERITY"]] |
118 | | - for alarm in processor.list_alarms(): |
119 | | - row = [ |
120 | | - alarm.trigger_time, |
121 | | - alarm.name, |
122 | | - alarm.sequence_number, |
123 | | - alarm.severity, |
| 144 | + rows: List[List[Any]] = [ |
| 145 | + [ |
| 146 | + "TIME", |
| 147 | + "TYPE", |
| 148 | + "SUBJECT", |
| 149 | + "SEQNO", |
| 150 | + "SEVERITY", |
| 151 | + "TRIP VALUE", |
| 152 | + "SAMPLE COUNT", |
| 153 | + "VIOLATION COUNT", |
124 | 154 | ] |
125 | | - rows.append(row) |
| 155 | + ] |
| 156 | + for alarm in processor.list_alarms(): |
| 157 | + if isinstance(alarm, ParameterAlarm): |
| 158 | + row = [ |
| 159 | + alarm.trigger_time, |
| 160 | + "PARAMETER", |
| 161 | + alarm.name, |
| 162 | + alarm.sequence_number, |
| 163 | + alarm.severity, |
| 164 | + format_parameter_trip_value(alarm), |
| 165 | + alarm.count, |
| 166 | + alarm.violation_count, |
| 167 | + ] |
| 168 | + rows.append(row) |
| 169 | + elif isinstance(alarm, EventAlarm): |
| 170 | + row = [ |
| 171 | + alarm.trigger_time, |
| 172 | + "EVENT", |
| 173 | + alarm.name, |
| 174 | + alarm.sequence_number, |
| 175 | + alarm.severity, |
| 176 | + format_event_trip_value(alarm), |
| 177 | + alarm.count, |
| 178 | + alarm.violation_count, |
| 179 | + ] |
| 180 | + rows.append(row) |
126 | 181 | utils.print_table(rows) |
127 | 182 |
|
128 | 183 | def log(self, args): |
@@ -151,15 +206,51 @@ def log(self, args): |
151 | 206 | if most_recent_only: |
152 | 207 | iterator = reversed(list(islice(iterator, 0, int(args.lines)))) |
153 | 208 |
|
154 | | - rows: List[List[Any]] = [["TIME", "NAME", "SEQNO", "SEVERITY"]] |
155 | | - for alarm in iterator: |
156 | | - row = [ |
157 | | - alarm.trigger_time, |
158 | | - alarm.name, |
159 | | - alarm.sequence_number, |
160 | | - alarm.severity, |
| 209 | + rows: List[List[Any]] = [ |
| 210 | + [ |
| 211 | + "TIME", |
| 212 | + "TYPE", |
| 213 | + "SUBJECT", |
| 214 | + "SEQNO", |
| 215 | + "SEVERITY", |
| 216 | + "TRIP VALUE", |
| 217 | + "SAMPLE COUNT", |
| 218 | + "VIOLATION COUNT", |
161 | 219 | ] |
162 | | - rows.append(row) |
| 220 | + ] |
| 221 | + for alarm in iterator: |
| 222 | + |
| 223 | + # Avoid defaulting to WATCH severity if severity is not set. |
| 224 | + # It 'should' always be set, however it has been seen missing |
| 225 | + # for unknown reason. |
| 226 | + severity = alarm.severity if alarm._proto.HasField("severity") else None |
| 227 | + |
| 228 | + if isinstance(alarm, ParameterAlarm): |
| 229 | + trip_value = format_parameter_trip_value(alarm) |
| 230 | + row = [ |
| 231 | + alarm.trigger_time, |
| 232 | + "PARAMETER", |
| 233 | + alarm.name, |
| 234 | + alarm.sequence_number, |
| 235 | + "-" if severity is None else severity, |
| 236 | + "-" if trip_value is None else trip_value, |
| 237 | + alarm.count, |
| 238 | + alarm.violation_count, |
| 239 | + ] |
| 240 | + rows.append(row) |
| 241 | + elif isinstance(alarm, EventAlarm): |
| 242 | + trip_value = format_event_trip_value(alarm) |
| 243 | + row = [ |
| 244 | + alarm.trigger_time, |
| 245 | + "EVENT", |
| 246 | + alarm.name, |
| 247 | + alarm.sequence_number, |
| 248 | + "-" if severity is None else severity, |
| 249 | + "-" if trip_value is None else trip_value, |
| 250 | + alarm.count, |
| 251 | + alarm.violation_count, |
| 252 | + ] |
| 253 | + rows.append(row) |
163 | 254 | utils.print_table(rows) |
164 | 255 |
|
165 | 256 | def acknowledge(self, args): |
|
0 commit comments