package org.yamcs.web.websocket; import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yamcs.ProcessorException; import org.yamcs.Processor; import org.yamcs.alarms.ActiveAlarm; import org.yamcs.alarms.AlarmListener; import org.yamcs.alarms.AlarmServer; import org.yamcs.protobuf.Alarms.AcknowledgeInfo; import org.yamcs.protobuf.Alarms.AlarmData; import org.yamcs.protobuf.SchemaAlarms; import org.yamcs.protobuf.Web.WebSocketServerMessage.WebSocketReplyData; import org.yamcs.protobuf.Yamcs.NamedObjectId; import org.yamcs.protobuf.Yamcs.ProtoDataType; import org.yamcs.security.Privilege; import org.yamcs.utils.TimeEncoding; /** * Provides realtime alarm subscription via web. */ public class AlarmResource extends AbstractWebSocketResource implements AlarmListener { private static final Logger log = LoggerFactory.getLogger(AlarmResource.class); public static final String RESOURCE_NAME = "alarms"; public AlarmResource(WebSocketProcessorClient client) { super(client); } @Override public WebSocketReplyData processRequest(WebSocketDecodeContext ctx, WebSocketDecoder decoder) throws WebSocketException { switch (ctx.getOperation()) { case "subscribe": return subscribe(ctx.getRequestId()); case "unsubscribe": return unsubscribe(ctx.getRequestId()); default: throw new WebSocketException(ctx.getRequestId(), "Unsupported operation '"+ctx.getOperation()+"'"); } } private WebSocketReplyData subscribe(int requestId) throws WebSocketException { try { WebSocketReplyData reply = toAckReply(requestId); wsHandler.sendReply(reply); doSubscribe(); return null; } catch (IOException e) { log.error("Exception when sending data", e); return null; } } private WebSocketReplyData unsubscribe(int requestId) throws WebSocketException { doUnsubscribe(); return toAckReply(requestId); } @Override public void quit() { doUnsubscribe(); } @Override public void switchProcessor(Processor oldProcessor, Processor newProcessor) throws ProcessorException { doUnsubscribe(); super.switchProcessor(oldProcessor, newProcessor); doSubscribe(); } private void doSubscribe() { if (processor.hasAlarmServer()) { AlarmServer alarmServer = processor.getParameterRequestManager().getAlarmServer(); for (ActiveAlarm activeAlarm : alarmServer.getActiveAlarms().values()) { sendAlarm(AlarmData.Type.ACTIVE, activeAlarm); } alarmServer.subscribe(this); } } private void doUnsubscribe() { if (processor.hasAlarmServer()) { AlarmServer alarmServer = processor.getParameterRequestManager().getAlarmServer(); alarmServer.unsubscribe(this); } } @Override public void notifyTriggered(ActiveAlarm activeAlarm) { sendAlarm(AlarmData.Type.TRIGGERED, activeAlarm); } @Override public void notifySeverityIncrease(ActiveAlarm activeAlarm) { sendAlarm(AlarmData.Type.SEVERITY_INCREASED, activeAlarm); } @Override public void notifyParameterValueUpdate(ActiveAlarm activeAlarm) { sendAlarm(AlarmData.Type.PVAL_UPDATED, activeAlarm); } @Override public void notifyAcknowledged(ActiveAlarm activeAlarm) { sendAlarm(AlarmData.Type.ACKNOWLEDGED, activeAlarm); } @Override public void notifyCleared(ActiveAlarm activeAlarm) { sendAlarm(AlarmData.Type.CLEARED, activeAlarm); } private void sendAlarm(AlarmData.Type type, ActiveAlarm activeAlarm) { NamedObjectId parameterId = NamedObjectId.newBuilder() .setName(activeAlarm.triggerValue.getParameter().getQualifiedName()) .build(); AlarmData.Builder alarmb = AlarmData.newBuilder(); alarmb.setType(type); alarmb.setSeqNum(activeAlarm.id); alarmb.setTriggerValue(activeAlarm.triggerValue.toGpb(parameterId)); alarmb.setMostSevereValue(activeAlarm.mostSevereValue.toGpb(parameterId)); alarmb.setCurrentValue(activeAlarm.currentValue.toGpb(parameterId)); alarmb.setViolations(activeAlarm.violations); if (activeAlarm.acknowledged) { AcknowledgeInfo.Builder acknowledgeb = AcknowledgeInfo.newBuilder(); String username = activeAlarm.usernameThatAcknowledged; if (username == null) { username = (activeAlarm.autoAcknowledge) ? "autoAcknowledged" : Privilege.getDefaultUser(); } acknowledgeb.setAcknowledgedBy(username); if(activeAlarm.message!=null) { acknowledgeb.setAcknowledgeMessage(activeAlarm.message); } acknowledgeb.setAcknowledgeTime(activeAlarm.acknowledgeTime); acknowledgeb.setAcknowledgeTimeUTC(TimeEncoding.toString(activeAlarm.acknowledgeTime)); alarmb.setAcknowledgeInfo(acknowledgeb.build()); } try { wsHandler.sendData(ProtoDataType.ALARM_DATA, alarmb.build(), SchemaAlarms.AlarmData.WRITE); } catch (Exception e) { log.warn("got error when sending alarm, quitting", e); quit(); } } }