src/app/data/alarm.service.ts
Service that connects and receives Alarm messages from the IAS Webserver through Websockets
constructor(cdbService: CdbService, httpClientService: HttpClientService, authService: AuthService, ngZone: NgZone)
|
||||||||||||||||||||
Defined in src/app/data/alarm.service.ts:153
|
||||||||||||||||||||
Builds an instance of the service
Parameters :
|
acknowledgeAlarms | ||||||||||||||||
acknowledgeAlarms(alarms_ids: string[], message: string, user: string)
|
||||||||||||||||
Defined in src/app/data/alarm.service.ts:433
|
||||||||||||||||
Acknowledges a list of Alarms with a message
Parameters :
Returns :
any
response of the HTTP request of the acknowledge |
add_or_update_alarm | ||||||||
add_or_update_alarm(alarm: Alarm)
|
||||||||
Defined in src/app/data/alarm.service.ts:585
|
||||||||
Adds or updates an Alarm to the AlarmService
Parameters :
Returns :
void
|
bufferStreamTasks | ||||||
bufferStreamTasks(change: any)
|
||||||
Defined in src/app/data/alarm.service.ts:255
|
||||||
Setup tasks for data received in the buffer
Parameters :
Returns :
void
|
changeAlarms | ||||||||
changeAlarms(changes: any)
|
||||||||
Defined in src/app/data/alarm.service.ts:224
|
||||||||
Sends an Alarm change event
Parameters :
Returns :
void
|
changeCounter | ||||||
changeCounter(any: any)
|
||||||
Defined in src/app/data/alarm.service.ts:233
|
||||||
Sends a counters change event
Parameters :
Returns :
void
|
clearSoundsIfAck | ||||||||
clearSoundsIfAck(alarm: Alarm)
|
||||||||
Defined in src/app/data/alarm.service.ts:654
|
||||||||
Stops the sound of a given Alarm, only if the sound is being repeated It is intended to be used when critical alarms (repeated) are acknowledged. Once the sound stops, it checks if there is another non-acknowledged alarm and plays its sound repeatedly. by calling AlarmService.html#playAlarmSound
Parameters :
Returns :
void
|
connect |
connect()
|
Defined in src/app/data/alarm.service.ts:345
|
Start connection to the backend through websockets
Returns :
void
|
counterStreamTasks | ||||||
counterStreamTasks(countByView: any)
|
||||||
Defined in src/app/data/alarm.service.ts:262
|
||||||
Setup tasks for counter data
Parameters :
Returns :
void
|
destroy |
destroy()
|
Defined in src/app/data/alarm.service.ts:365
|
Disconnect from the backend
Returns :
void
|
emitSound | ||||||||||||
emitSound(sound: string, repeat: boolean)
|
||||||||||||
Defined in src/app/data/alarm.service.ts:634
|
||||||||||||
Reproduces a sound
Parameters :
Returns :
void
|
get | ||||||
get(core_id: string)
|
||||||
Defined in src/app/data/alarm.service.ts:386
|
||||||
* ALARM HANDLING **
Parameters :
Returns :
Alarm
|
getAlarm | ||||||||
getAlarm(config: AlarmConfig)
|
||||||||
Defined in src/app/data/alarm.service.ts:404
|
||||||||
Returns the instance of the Alarm associated to a given AlarmConfig
Parameters :
Returns :
Alarm
the { |
getAlarmList |
getAlarmList()
|
Defined in src/app/data/alarm.service.ts:539
|
* HANDLING OF ALARM MESSAGES FROM THE CORE **
Returns :
void
|
getChangesFromBuffer |
getChangesFromBuffer()
|
Defined in src/app/data/alarm.service.ts:280
|
Get list of alarms with graphical components to update from the buffer
Returns :
{}
|
getConnectionPath |
getConnectionPath()
|
Defined in src/app/data/alarm.service.ts:358
|
Connection path using authentication data
Returns :
string
|
getMissingAcks | ||||||||
getMissingAcks(alarm_id: string)
|
||||||||
Defined in src/app/data/alarm.service.ts:456
|
||||||||
Get information about old tickets related to a target alarm
Parameters :
Returns :
any
response of the HTTP request with a dictionary with information about missing acks |
getName | ||||||||
getName(config: AlarmConfig)
|
||||||||
Defined in src/app/data/alarm.service.ts:416
|
||||||||
Returns the custom_name of the Alarm given a corresponding AlarmConfig. If there is no custom_name, it returns the alarm_id
Parameters :
Returns :
string
the name associated to the given { |
getShelveRegistries | ||||||||||||
getShelveRegistries(alarm_id: string, status: number)
|
||||||||||||
Defined in src/app/data/alarm.service.ts:472
|
||||||||||||
Gets the open ShelveRegistry for an Alarm
Parameters :
Returns :
any
response of the HTTP request with a dictionary with information about missing acks |
initialize |
initialize()
|
Defined in src/app/data/alarm.service.ts:300
|
Start connection to the backend through websockets
Returns :
void
|
isAlarmIndexAvailable | ||||||||
isAlarmIndexAvailable(core_id: string)
|
||||||||
Defined in src/app/data/alarm.service.ts:395
|
||||||||
Returns a boolean to check if there is information available about an alarm
Parameters :
Returns :
boolean
true if there is information about the alarm |
playAlarmSound | ||||||||
playAlarmSound(alarm: Alarm)
|
||||||||
Defined in src/app/data/alarm.service.ts:618
|
||||||||
Reproduces the sound of a given Alarm
Parameters :
Returns :
void
|
readAlarmMessagesList | |||||||||||||||
readAlarmMessagesList(alarmsList: Object[], allChanged: boolean)
|
|||||||||||||||
Defined in src/app/data/alarm.service.ts:551
|
|||||||||||||||
Reads a list of alarm messages form the Core and add them to the service alarms list. Sends the corresponding notification in the AlarmService, by calling AlarmService
Parameters :
Returns :
void
|
readCountByViewMessage | ||||||
readCountByViewMessage(countByView: Object)
|
||||||
Defined in src/app/data/alarm.service.ts:570
|
||||||
Reads the count by view object received from the webserver
Parameters :
Returns :
void
|
resetCountByView |
resetCountByView()
|
Defined in src/app/data/alarm.service.ts:577
|
Method to clear the count by view if there is the ws connection is closed
Returns :
void
|
resetTimer |
resetTimer()
|
Defined in src/app/data/alarm.service.ts:696
|
Resets the status connection check timer The timer's period is equal to the broadcastThreshold obtained by CdbService.html#getBroadcastRate
Returns :
void
|
setPeriodicalPullFromBuffer |
setPeriodicalPullFromBuffer()
|
Defined in src/app/data/alarm.service.ts:242
|
* SERVICE INITIALIZATION **
Returns :
void
|
shelveAlarm | ||||||||||||||||||||
shelveAlarm(alarm_id: string, message: string, timeout: string, user: string)
|
||||||||||||||||||||
Defined in src/app/data/alarm.service.ts:490
|
||||||||||||||||||||
Shelves and Alarm with a message
Parameters :
Returns :
any
response of the HTTP request of the shelve |
stopSound |
stopSound()
|
Defined in src/app/data/alarm.service.ts:673
|
If there is a sound defined, it stops it
Returns :
void
|
triggerAlarmsNonValidConnectionState |
triggerAlarmsNonValidConnectionState()
|
Defined in src/app/data/alarm.service.ts:684
|
* PERIODIC CHECK OF VALIDITY OF ALARMS **
Returns :
void
|
unshelveAlarms | ||||||||||||
unshelveAlarms(alarms_ids: string[], message: string)
|
||||||||||||
Defined in src/app/data/alarm.service.ts:515
|
||||||||||||
Shelves and Alarm with a message
Parameters :
Returns :
any
response of the HTTP request of the shelve |
updateAlarmChangeBuffer | ||||||
updateAlarmChangeBuffer(changes: string)
|
||||||
Defined in src/app/data/alarm.service.ts:269
|
||||||
Method to manage the update of the buffer for a new alarm change
Parameters :
Returns :
void
|
Public alarmChangeBufferList |
Type : []
|
Default value : []
|
Defined in src/app/data/alarm.service.ts:116
|
Stream of notifications to control the delivery of changes in the dictionary of Alarm objects |
Public alarmChangeBufferStream |
Default value : new BehaviorSubject<any>(true)
|
Defined in src/app/data/alarm.service.ts:106
|
Stream of notifications to control the delivery of changes in the dictionary of Alarm objects |
Public alarmChangeInputStream |
Default value : new BehaviorSubject<any>(true)
|
Defined in src/app/data/alarm.service.ts:91
|
Stream of notifications to control the delivery of changes in the dictionary of Alarm objects |
Public alarmChangeStream |
Default value : new BehaviorSubject<any>(true)
|
Defined in src/app/data/alarm.service.ts:86
|
Stream of notifications of changes in the dictionary of Alarm objects |
Public alarmsArray |
Type : Alarm[]
|
Default value : []
|
Defined in src/app/data/alarm.service.ts:76
|
Array of Alarm objects |
Public alarmsIndexes |
Type : literal type
|
Default value : {}
|
Defined in src/app/data/alarm.service.ts:81
|
Index for the alarmsArray { core_id: arrayIndex } |
Public canSound |
Type : boolean
|
Defined in src/app/data/alarm.service.ts:128
|
Defines wether or not the display should emit sounds when alarms are triggered. It is used to avoid sounds when the page is refreshed, and only allow them after that |
Public connectionStatusStream |
Default value : new BehaviorSubject<any>(false)
|
Defined in src/app/data/alarm.service.ts:71
|
Stream of notifications of changes in the status of the service connection |
Public connectionStatusTimer |
Type : any
|
Defined in src/app/data/alarm.service.ts:153
|
Connection status timer |
Public countByView |
Type : object
|
Default value : {}
|
Defined in src/app/data/alarm.service.ts:148
|
Information about the count of alarms by view |
Public counterChangeBufferStream |
Default value : new BehaviorSubject<any>({})
|
Defined in src/app/data/alarm.service.ts:111
|
Stream of notifications to control the delivery of changes in the counter related to the dictionary of Alarm objects |
Public counterChangeInputStream |
Default value : new BehaviorSubject<any>({})
|
Defined in src/app/data/alarm.service.ts:101
|
Stream of notifications to control the delivery of changes in the counter related to the dictionary of Alarm objects |
Public counterChangeStream |
Default value : new BehaviorSubject<any>({})
|
Defined in src/app/data/alarm.service.ts:96
|
Stream of notifications of changes in the counter related to the dictionary of Alarm objects |
Public isInitialized |
Default value : false
|
Defined in src/app/data/alarm.service.ts:143
|
Defines wether or not the service is initialized |
Public lastReceivedMessageTimestamp |
Type : number
|
Default value : (new Date).getTime()
|
Defined in src/app/data/alarm.service.ts:65
|
Timestamp related with the last received message |
Public sound |
Type : Howl
|
Defined in src/app/data/alarm.service.ts:133
|
Reference to the audio object used to play the sounds |
Public soundingAlarm |
Type : string
|
Defined in src/app/data/alarm.service.ts:138
|
Id of the currenlty sounding Alarm |
Public webSocketBridge |
Type : WebSocketBridge
|
Default value : new WebSocketBridge()
|
Defined in src/app/data/alarm.service.ts:122
|
Django Channels WebsocketBridge, used to connect to Django Channels through Websockets |
import { Injectable, NgZone } from '@angular/core';
import { map, auditTime } from 'rxjs/operators';
import { BehaviorSubject } from 'rxjs';
import { interval } from 'rxjs';
import { WebSocketBridge } from 'django-channels';
import { Howl, Howler} from 'howler';
import { environment } from '../../environments/environment';
import { Alarm, Validity, Value } from '../data/alarm';
import { AlarmConfig } from '../data/alarm-config';
import { BackendUrls, Streams, Assets } from '../settings';
import { CdbService } from '../data/cdb.service';
import { HttpClientService } from './http-client.service';
import { AuthService } from '../auth/auth.service';
/**
* Class used to model the different sound options and their corresponding audio files
*/
export class AlarmSounds {
/** This is the type for alarms with no sound */
static none = '';
/** The name of the audio file associated to the sound TYPE1 */
static type1 = 'Alarm_Sound_1.mp3';
/** The name of the audio file associated to the sound TYPE2 */
static type2 = 'Alarm_Sound_2.mp3';
/** The name of the audio file associated to the sound TYPE3 */
static type3 = 'Alarm_Sound_3.mp3';
/** The name of the audio file associated to the sound TYPE4 */
static type4 = 'Alarm_Sound_4.mp3';
/**
* Given a sound type, retruns the associated audiofile
* @param {string} sound The sound type, e.g. TYPE1, TYPE2, etc.
* @returns {string} the filepath of the corresponding audio file
*/
static getSoundsource(sound: string): string {
if (sound === 'TYPE1') {
return Assets.SOUNDS + AlarmSounds.type1;
} else if (sound === 'TYPE2') {
return Assets.SOUNDS + AlarmSounds.type2;
} else if (sound === 'TYPE3') {
return Assets.SOUNDS + AlarmSounds.type3;
} else if (sound === 'TYPE4') {
return Assets.SOUNDS + AlarmSounds.type4;
}
return null;
}
}
/**
* Service that connects and receives {@link Alarm} messages from the
* IAS Webserver through Websockets
*/
@Injectable()
export class AlarmService {
/**
* Timestamp related with the last received message
*/
public lastReceivedMessageTimestamp: number = (new Date).getTime();
/**
* Stream of notifications of changes in
* the status of the service connection
*/
public connectionStatusStream = new BehaviorSubject<any>(false);
/**
* Array of {@link Alarm} objects
*/
public alarmsArray: Alarm[] = [];
/**
* Index for the alarmsArray { core_id: arrayIndex }
*/
public alarmsIndexes: {[core_id: string]: number} = {};
/**
* Stream of notifications of changes in the dictionary of {@link Alarm} objects
*/
public alarmChangeStream = new BehaviorSubject<any>(true);
/**
* Stream of notifications to control the delivery of changes in the dictionary of {@link Alarm} objects
*/
public alarmChangeInputStream = new BehaviorSubject<any>(true);
/**
* Stream of notifications of changes in the counter related to the dictionary of {@link Alarm} objects
*/
public counterChangeStream = new BehaviorSubject<any>({});
/**
* Stream of notifications to control the delivery of changes in the counter related to the dictionary of {@link Alarm} objects
*/
public counterChangeInputStream = new BehaviorSubject<any>({});
/**
* Stream of notifications to control the delivery of changes in the dictionary of {@link Alarm} objects
*/
public alarmChangeBufferStream = new BehaviorSubject<any>(true);
/**
* Stream of notifications to control the delivery of changes in the counter related to the dictionary of {@link Alarm} objects
*/
public counterChangeBufferStream = new BehaviorSubject<any>({});
/**
* Stream of notifications to control the delivery of changes in the dictionary of {@link Alarm} objects
*/
public alarmChangeBufferList = [];
/**
* Django Channels WebsocketBridge,
* used to connect to Django Channels through Websockets
*/
public webSocketBridge: WebSocketBridge = new WebSocketBridge();
/**
* Defines wether or not the display should emit sounds when alarms are triggered.
* It is used to avoid sounds when the page is refreshed, and only allow them after that
*/
public canSound: boolean;
/**
* Reference to the audio object used to play the sounds
*/
public sound: Howl;
/**
* Id of the currenlty sounding Alarm
*/
public soundingAlarm: string;
/**
* Defines wether or not the service is initialized
*/
public isInitialized = false;
/**
* Information about the count of alarms by view
*/
public countByView = {};
/**
* Connection status timer
*/
public connectionStatusTimer: any;
/**
* Builds an instance of the service
* @param {CdbService} cdbService Service used to get complementary alarm information
* @param {HttpClientService} httpClientService Service used to perform HTTP requests
* @param {AuthService} authService Service used for authentication
* @param {NgZone} ngZone Service used for executing work inside or outside of the Angular Zone
*/
constructor(
private cdbService: CdbService,
private httpClientService: HttpClientService,
private authService: AuthService,
private ngZone: NgZone
) {
this.connectionStatusStream.subscribe(
value => {
if (value === false) {
this.triggerAlarmsNonValidConnectionState();
}
}
);
this.authService.loginStatusStream.subscribe(
value => {
if (value === true) {
this.initialize();
} else {
this.destroy();
}
}
);
this.alarmChangeInputStream.subscribe(
changes => {
this.ngZone.run(
() => {
this.alarmChangeStream.next(changes);
}
);
}
);
this.counterChangeInputStream.subscribe(
countByView => {
this.ngZone.run(
() => {
this.counterChangeStream.next(countByView);
}
);
}
);
this.alarmChangeBufferStream.subscribe(
change => {
this.bufferStreamTasks(change);
}
);
this.counterChangeBufferStream.subscribe(
countByView => {
this.counterStreamTasks(countByView);
}
);
}
/**
* Sends an {@link Alarm} change event
*
* @param {Any} changes the list of core_ids of the updated Alarms, or 'all' if all were updated
*/
changeAlarms(changes: any) {
this.alarmChangeBufferStream.next(changes);
}
/**
* Sends a counters change event
*
* @param {Any} changes the dictionary of count value sindexed by view
*/
changeCounter(any: any) {
this.counterChangeBufferStream.next(any);
}
/******* SERVICE INITIALIZATION *******/
/**
* Setup periodical push from buffer
*/
setPeriodicalPullFromBuffer() {
setInterval( () => {
const changes = this.getChangesFromBuffer();
if (changes.length > 0) {
this.alarmChangeInputStream.next(changes);
this.counterChangeInputStream.next(this.countByView);
}
}, 250);
}
/**
* Setup tasks for data received in the buffer
*/
bufferStreamTasks(change: any) {
this.updateAlarmChangeBuffer(change);
}
/**
* Setup tasks for counter data
*/
counterStreamTasks(countByView: any) {
this.readCountByViewMessage(countByView);
}
/**
* Method to manage the update of the buffer for a new alarm change
*/
updateAlarmChangeBuffer(changes: string) {
if (changes === 'all') {
this.alarmChangeBufferList = ['all'];
} else {
this.alarmChangeBufferList = this.alarmChangeBufferList.concat(changes);
}
}
/**
* Get list of alarms with graphical components to update from the buffer
*/
getChangesFromBuffer() {
if (this.alarmChangeBufferList.indexOf('all') >= 0) {
this.alarmChangeBufferList = [];
return ['all'];
}
let changes: string[] = [];
const alarmChangeBuffer = new Set(this.alarmChangeBufferList);
this.alarmChangeBufferList = [];
if (alarmChangeBuffer.size > 10 ) {
// console.log('Changes over buffer size reference ', this.alarmChangeBuffer.size);
changes = ['all'];
} else {
changes = Array.from(alarmChangeBuffer);
}
return changes;
}
/**
* Start connection to the backend through websockets
*/
initialize() {
if (this.isInitialized || !this.authService.loginStatus) {
return;
}
this.cdbService.initialize();
this.isInitialized = true;
this.canSound = false;
this.connect();
this.ngZone.runOutsideAngular(
() => {
this.webSocketBridge.socket.addEventListener(
'open', () => {
this.connectionStatusStream.next(true);
this.getAlarmList();
}
);
this.webSocketBridge.socket.addEventListener(
'close', () => {
this.resetCountByView();
}
);
this.webSocketBridge.demultiplex(Streams.ALARMS, (payload: any, streamName: any) => {
// console.log('notify ', payload);
if (this.authService.loginStatus) {
this.resetTimer();
this.readAlarmMessagesList(payload.alarms, false);
this.counterChangeBufferStream.next(payload.counters);
}
});
this.webSocketBridge.demultiplex(Streams.UPDATES, (payload: any, streamName: any) => {
// console.log('request', payload);
if (this.authService.loginStatus) {
this.resetTimer();
this.readAlarmMessagesList(payload.alarms, true);
this.counterChangeBufferStream.next(payload.counters);
}
});
}
);
this.setPeriodicalPullFromBuffer();
}
/**
* Start connection to the backend through websockets
*/
connect() {
this.ngZone.runOutsideAngular(
() => {
const connectionPath = this.getConnectionPath();
this.webSocketBridge.connect(connectionPath);
this.webSocketBridge.listen(connectionPath);
console.log('Connected to webserver at');
});
}
/**
* Connection path using authentication data
*/
getConnectionPath() {
return environment.websocketPath + '?token=' + this.authService.getToken();
}
/**
* Disconnect from the backend
*/
destroy() {
// Close connection
if (this.isInitialized) {
this.webSocketBridge.stream(Streams.UPDATES).send({
'action': 'close'
});
this.webSocketBridge.socket.close(
1000, 'User logout', {keepClosed: true});
this.resetCountByView();
}
this.isInitialized = false;
console.log('Connection to webserver closed');
}
/******* ALARM HANDLING *******/
/**
* Returns an Alarm object
* @param core_id core_id of the Alarm to return
* @returns {Alarm} Alarm object corresponding to the given core_id
*/
get(core_id: string): Alarm {
return this.alarmsArray[this.alarmsIndexes[core_id]] as Alarm;
}
/**
* Returns a boolean to check if there is information available about an alarm
* @param core_id core_id of the Alarm
* @returns {boolean} true if there is information about the alarm
*/
isAlarmIndexAvailable(core_id: string): boolean {
return (core_id in this.alarmsIndexes);
}
/**
* Returns the instance of the {@link Alarm} associated to a given {@link AlarmConfig}
* @param {AlarmConfig} config the corresponding AlarmConfig from where to get the {@link Alarm}
* @returns {Alarm} the {@link Alarm} associated to the given {@link AlarmConfig}
*/
getAlarm(config: AlarmConfig): Alarm {
if (config) {
return this.get(config.alarm_id);
}
}
/**
* Returns the custom_name of the {@link Alarm} given a corresponding {@link AlarmConfig}.
* If there is no custom_name, it returns the alarm_id
* @param {AlarmConfig} config the corresponding AlarmConfig from where to get the {@link Alarm}
* @returns {string} the name associated to the given {@link AlarmConfig}
*/
getName(config: AlarmConfig): string {
if (config) {
if (config.custom_name) {
return config.custom_name;
} else {
return config.alarm_id;
}
}
}
/**
* Acknowledges a list of Alarms with a message
* @param {string[]} alarm_ids list of ids of the alarms to acknowledge
* @param {string} message message of the acknowledgement
* @param {string} user user that performs the acknowledgement
* @returns {json} response of the HTTP request of the acknowledge
*/
acknowledgeAlarms(alarms_ids: string[], message: string, user: string): any {
const data = {
'alarms_ids': alarms_ids,
'message': message,
'user': user
};
return this.httpClientService.put(BackendUrls.TICKETS_MULTIPLE_ACK, data).pipe(
map(
(response) => {
for (const id of alarms_ids) {
const alarm = this.get(id);
alarm.acknowledge();
}
return response;
}
));
}
/**
* Get information about old tickets related to a target alarm
* @param alarm_id id of the target alarm
* @returns {any[]} response of the HTTP request with a dictionary with information about missing acks
*/
getMissingAcks(alarm_id: string) {
const url = BackendUrls.TICKETS_INFO + '?alarm_id=' + alarm_id;
return this.httpClientService.get(url).pipe(
map(
(response) => {
return response;
}
));
}
/**
* Gets the open {@link ShelveRegistry} for an {@link Alarm}
* @param {string} alarm_id id of the target alarm
* @param {number} status id of the target alarm
* @returns {json} response of the HTTP request with a dictionary with information about missing acks
*/
getShelveRegistries(alarm_id: string, status: number): any {
const url = BackendUrls.SHELVE_REGS_FILTER + '?alarm_id=' + alarm_id + '&status=' + status;
return this.httpClientService.get(url).pipe(
map(
(response) => {
return response;
}
));
}
/**
* Shelves and {@link Alarm} with a message
* @param {string} alarm_id id of the alarm to shelve
* @param {string} message message of the shelving
* @param {string} timeout the timeout for the shelving
* @param {string} user the user who performed the shelving
* @returns {json} response of the HTTP request of the shelve
*/
shelveAlarm(alarm_id: string, message: string, timeout: string, user: string): any {
const data = {
'alarm_id': alarm_id,
'message': message,
'timeout': timeout,
'user': user
};
return this.httpClientService.post(BackendUrls.SHELVE_API, data).pipe(
map(
(response) => {
if (response['status'] === 201) {
const alarm = this.get(alarm_id);
alarm.shelve();
}
return response;
}
));
}
/**
* Shelves and {@link Alarm} with a message
* @param {string[]} alarms_ids id of the alarm to shelve
* @param {string} message message of the shelving
* @returns {json} response of the HTTP request of the shelve
*/
unshelveAlarms(alarms_ids: string[], message: string): any {
const data = {
'alarms_ids': alarms_ids,
};
return this.httpClientService.put(BackendUrls.UNSHELVE_API, data).pipe(
map(
(response) => {
if (response['status'] === 200) {
for (const id of alarms_ids) {
const alarm = this.get(id);
alarm.unshelve();
}
}
return response;
}
));
}
/******* HANDLING OF ALARM MESSAGES FROM THE CORE *******/
/**
* Get the complete list of alarms from the webserver database
* through the websocket
*/
getAlarmList() {
this.webSocketBridge.stream(Streams.UPDATES).send({
'action': 'list'
});
}
/**
* Reads a list of alarm messages form the Core and add them to the service alarms list.
* Sends the corresponding notification in the {@link AlarmService#alarmChangeBufferStream}, by calling {@link AlarmService#changeAlarms}
* @param {Object[]} alarmsList list of dictionaries with values for alarm fields (as generic objects)
* @param {boolean} allChanged true if the list is a general change in all the alarms, false if not
*/
readAlarmMessagesList(alarmsList: Object[], allChanged: boolean = false) {
const changed = [];
for (const obj of alarmsList) {
const alarm = Alarm.asAlarm(obj);
this.add_or_update_alarm(alarm);
changed.push(alarm.core_id);
}
if (allChanged) {
this.changeAlarms('all');
} else {
this.changeAlarms(changed);
}
this.canSound = true;
}
/**
* Reads the count by view object received from the webserver
* @param {Object} countByView
*/
readCountByViewMessage(countByView: Object) {
this.countByView = countByView;
}
/**
* Method to clear the count by view if there is the ws connection is closed
*/
resetCountByView() {
this.countByView = {};
}
/**
* Adds or updates an {@link Alarm} to the AlarmService
* @param {Alarm} alarm the {@link Alarm} to add or update
*/
add_or_update_alarm(alarm: Alarm) {
let old_alarm_value = Value.cleared;
let old_alarm_ack = true;
if (alarm.core_id in this.alarmsIndexes) {
const old_alarm = this.alarmsArray[this.alarmsIndexes[alarm.core_id]];
old_alarm_value = old_alarm.value;
old_alarm_ack = old_alarm.ack;
this.alarmsArray[this.alarmsIndexes[alarm.core_id]] = alarm;
} else {
const newLength = this.alarmsArray.push(alarm);
this.alarmsIndexes[alarm.core_id] = newLength - 1;
}
if (old_alarm_value === Value.cleared && alarm.value !== Value.cleared) {
if (alarm.sound !== 'NONE') {
this.playAlarmSound(alarm);
}
}
if (old_alarm_value !== Value.cleared && alarm.value === Value.cleared) {
if (alarm.sound !== 'NONE') {
this.clearSoundsIfAck(alarm);
}
}
if (!old_alarm_ack && alarm.ack) {
if (alarm.sound !== 'NONE') {
this.clearSoundsIfAck(alarm);
}
}
}
/**
* Reproduces the sound of a given {@link Alarm}
* @param {Alarm} alarm the {@link Alarm}
*/
playAlarmSound(alarm: Alarm) {
if (!this.canSound || alarm.shelved) {
return;
}
const repeat = alarm.shouldRepeat();
if (repeat || !this.sound || !this.sound.playing()) {
this.soundingAlarm = alarm.core_id;
this.emitSound(alarm.sound, repeat);
}
}
/**
* Reproduces a sound
* @param {string} sound the sound of the Alarm to reproduce
* @param {boolean} repeat true if the sound should be repeated, false if not.
*/
emitSound(sound: string, repeat: boolean) {
const soundToPlay = AlarmSounds.getSoundsource(sound);
if (soundToPlay === null || soundToPlay === '') {
return;
}
this.stopSound();
this.sound = new Howl({
src: [soundToPlay],
autoplay: true,
loop: repeat
});
}
/**
* Stops the sound of a given {@link Alarm}, only if the sound is being repeated
* It is intended to be used when critical alarms (repeated) are acknowledged.
* Once the sound stops, it checks if there is another non-acknowledged alarm and plays its sound repeatedly.
* by calling {@link AlarmService.html#playAlarmSound}
* @param {Alarm} alarm the {@link Alarm}
*/
clearSoundsIfAck(alarm: Alarm) {
this.stopSound();
if (!alarm.shouldRepeat()) {
return;
}
if (this.soundingAlarm === alarm.core_id) {
this.soundingAlarm = null;
for (alarm of this.alarmsArray) {
if (!alarm.ack && alarm.sound !== 'NONE' && alarm.shouldRepeat()) {
this.playAlarmSound(alarm);
return;
}
}
}
}
/**
* If there is a sound defined, it stops it
*/
stopSound() {
if (this.sound) {
this.sound.stop();
}
}
/******* PERIODIC CHECK OF VALIDITY OF ALARMS *******/
/**
* Set selected state to alarms under an non-valid connection
*/
triggerAlarmsNonValidConnectionState() {
for (const alarm of this.alarmsArray) {
alarm.validity = Validity.unreliable;
this.add_or_update_alarm(Alarm.asAlarm(Object.assign({}, alarm)));
}
this.changeAlarms('all');
}
/**
* Resets the status connection check timer
* The timer's period is equal to the broadcastThreshold obtained by {@link CdbService.html#getBroadcastRate}
*/
resetTimer() {
if (this.connectionStatusTimer) {
this.connectionStatusTimer.unsubscribe();
this.connectionStatusStream.next(true);
}
const broadcastThreshold = this.cdbService.getBroadcastThreshold();
this.connectionStatusTimer = interval(1000 * broadcastThreshold).subscribe( () => {
this.connectionStatusStream.next(false);
});
}
}