AlarmNotifications
PANDA Slow Control Alarm Daemon
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
alarmserverconnector.cpp
Go to the documentation of this file.
1 
34 #include "alarmserverconnector.h"
35 
36 #include <iostream>
37 #include <stdexcept>
38 #include <vector>
39 
40 #ifndef NOTUSELIBNOTIFY
41 #include <glib-2.0/glib.h>
42 #include <libnotify/notification.h>
43 #include <libnotify/notify.h>
44 #endif
45 
46 #include "alarmconfiguration.h"
47 #include "beedo.h"
48 #include "cmsclient.h"
49 #include "emailsender.h"
50 #include "exceptionhandler.h"
51 #include "flashlight.h"
52 
53 using namespace AlarmNotifications;
54 
55 AlarmServerConnector::AlarmServerConnector ( const bool desktopVersion, const bool activateBeedo )
56  : _desktopVersion ( desktopVersion ),
57  _activateBeedo ( activateBeedo ),
58  _cmsclient ( *this ),
59  _runwatcher ( true ),
60  _flashlighton ( false ),
61  _watcher ( boost::bind ( &AlarmServerConnector::startWatcher, this ) ),
62  _flashlightthread ( boost::bind ( &AlarmServerConnector::operateFlashLight, this ) ),
63  _oldestAlarm ( noAlarmActive )
64 {
66  throw std::logic_error ( "The \"beedo\" optoacoustic alarm can only be used in desktop mode!" );
67 #ifndef NOTUSELIBNOTIFY
68  notify_init ( "DCS Alarm System" );
69 #endif
70 }
71 
73 {
74  _runwatcher = false;
75  _watcher.join();
76  _flashlightthread.join();
77 #ifndef NOTUSELIBNOTIFY
78  notify_uninit();
79 #endif
80 }
81 
83 {
84  boost::lock_guard<boost::mutex> concurrencylock ( _statusmapmutex );
85  const std::string& pvname = status.getPVName();
86  auto entry = _statusmap.find ( pvname );
87  if ( checkSeverityString ( status.getSeverity() ) )
88  {
89  if ( entry != _statusmap.end() )
90  _statusmap.erase ( entry );
91  }
92  else
93  {
94  if ( entry == _statusmap.end() )
95  _statusmap.insert ( std::pair<std::string, AlarmStatusEntry> ( pvname, status ) );
96  else
97  ( *entry ).second.update ( status );
98  if ( _oldestAlarm == noAlarmActive )
99  _oldestAlarm = status.getTriggerTime();
100  }
101 }
102 
103 bool AlarmServerConnector::checkSeverityString ( const std::string& severity )
104 {
105  if ( severity == "OK" )
106  return true;
107  if ( severity.substr ( severity.length()-4, 4 ) == "_ACK" )
108  return true;
109  return false;
110 }
111 
113 {
114  while ( _runwatcher )
115  {
116  sleep ( 1 );
117  checkStatusMap();
118  }
119 }
120 
122 {
123  boost::lock_guard<boost::mutex> concurrencylock ( _statusmapmutex );
124  if ( _statusmap.size() == 0 && _oldestAlarm != noAlarmActive )
125  {
127  if ( _activateBeedo )
128  Beedo::stop();
129  }
130  /*for ( auto i = _statusmap.begin(); i != _statusmap.end(); i++ )
131  std::cout << ( *i ).second << std::endl;*/
132  if (
133  _statusmap.size() != 0
135  )
136  {
138  if ( _activateBeedo )
139  Beedo::start();
140  }
141  if (
142  _statusmap.size() != 0
144  )
146 }
147 
149 {
150  if ( _desktopVersion )
151  return; // Desktop version does not have a flashlight
152  while ( _runwatcher )
153  {
154  sleep ( 1 );
155  if (
157  && _statusmap.size() != 0
159  )
161  if ( _flashlighton && _statusmap.size() == 0 )
163  }
164 }
165 
167 {
168  if ( AlarmConfiguration::instance().getLaboratoryNotificationTimeout() == 0 )
169  return; // A value of 0 disables the notification via flash light
170  _flashlighton = true;
171  std::cout << "Flash light on!" << std::endl;
173 }
174 
176 {
177  if ( AlarmConfiguration::instance().getLaboratoryNotificationTimeout() == 0 )
178  return; // A value of 0 disables the notification via flash light
179  _flashlighton = false;
180  std::cout << "Flash light off!" << std::endl;
182 }
183 
185 {
186  if ( AlarmConfiguration::instance().getDesktopNotificationTimeout() == 0 )
187  return; // A timeout of 0 disables desktop notifications
188  std::vector<AlarmStatusEntry> alarmsToUse;
189  for ( auto i = _statusmap.begin(); i != _statusmap.end(); i++ )
190  {
191  if ( ( *i ).second.getTriggerTime() + AlarmConfiguration::instance().getDesktopNotificationTimeout() <= std::time ( nullptr ) )
192  {
193  if ( ! ( *i ).second.getDesktopNotificationSent() )
194  {
195  ( *i ).second.setDesktopNotificationSent ( true );
196  alarmsToUse.push_back ( AlarmStatusEntry ( ( *i ).second ) );
197  }
198  }
199  }
200  if ( alarmsToUse.size() > 0 )
201  {
202  boost::thread send ( boost::bind ( &AlarmServerConnector::sendDesktopNotification, this, std::move ( alarmsToUse ) ) );
203  send.detach();
204  }
205 }
206 
207 void AlarmServerConnector::sendDesktopNotification ( const std::vector<AlarmStatusEntry> alarm )
208 {
209  std::string alarmtext = "Alarm on this/these PV(s):\n";
210  for ( auto i = alarm.begin(); i != alarm.end(); i++ )
211  {
212  alarmtext += ( *i ).getPVName() + "\n";
213  }
214 #ifndef NOTUSELIBNOTIFY
215  NotifyNotification* n = notify_notification_new (
216  "Detector Alarm",
217  alarmtext.c_str(),
218  "dialog-warning"
219  );
220  notify_notification_set_timeout ( n, NOTIFY_EXPIRES_NEVER );
221  notify_notification_set_urgency ( n, NOTIFY_URGENCY_CRITICAL );
222  GError* showerror = nullptr;
223  notify_notification_show ( n, &showerror );
224  g_object_unref ( G_OBJECT ( n ) );
225 #else
226  std::string command = "notify-send -u critical -t 0 -i dialog-warning 'Detector Alarm' ";
227  command += std::string ( "'" );
228  command += alarmtext;
229  command += std::string ( "'" );
230  system ( command.c_str() );
231 #endif
232 }
233 
235 {
236  if ( _desktopVersion )
237  return; // The desktop version does not send e-mails
238  if ( AlarmConfiguration::instance().getEMailNotificationTimeout() == 0 )
239  return; // A timeout of 0 disables e-mail notifications
240  std::vector<AlarmStatusEntry> alarmsToUse;
241  for ( auto i = _statusmap.begin(); i != _statusmap.end(); i++ )
242  {
243  //if ( ( *i ).second.getTriggerTime() + AlarmConfiguration::instance().getEMailNotificationTimeout() <= std::time ( nullptr ) )
244  //{
245  if ( ! ( *i ).second.getEmailNotificationSent() )
246  {
247  ( *i ).second.setEmailNotificationSent ( true );
248  alarmsToUse.push_back ( AlarmStatusEntry ( ( *i ).second ) );
249  }
250  //}
251  }
252  if ( alarmsToUse.size() > 0 )
253  {
254  boost::thread send ( boost::bind ( &AlarmServerConnector::sendEMailNotification, this, std::move ( alarmsToUse ) ) );
255  send.detach();
256  }
257 }
258 
259 void AlarmServerConnector::sendEMailNotification ( const std::vector<AlarmStatusEntry> alarm )
260 {
262 }
263 
265 {
266  return _statusmap.size();
267 }
const std::string & getPVName() const noexcept
Query PV name.
void sendDesktopNotification(const std::vector< AlarmStatusEntry > alarm)
Fire desktop notification.
const bool _desktopVersion
Desktop version flag.
void switchFlashLightOn()
Switch laboratory flashlight on.
unsigned int getEMailNotificationTimeout() const noexcept
Timeout for sending an e-mail notification.
static const time_t noAlarmActive
Time of last alarm if no alarm is active.
static void switchOff() noexcept
Switch off red alarm flash light.
Definition: flashlight.cpp:79
void prepareEMailNotification()
Select alarms to be included in an e-mail notification.
Control USB relais for red alarm flash light.
static void stop() noexcept
Stop video playback.
Definition: beedo.h:211
boost::mutex _statusmapmutex
Mutex to protect the _statusmap.
void prepareDesktopNotification()
Select alarms to be included in a desktop notification.
unsigned int getLaboratoryNotificationTimeout() const noexcept
Timeout for starting alarm notification in the laboratory.
void notifyStatusChange(const AlarmStatusEntry status)
Notify AlarmServerConnector about alarm status change.
bool _flashlighton
Flashlight status flag.
static void start() noexcept
Start video playback.
Definition: beedo.h:199
bool checkSeverityString(const std::string &severity)
Check severity string in CSS Alarm Server message.
void switchFlashLightOff()
Switch laboratory flashlight off.
void startWatcher()
Start the watcher thread.
boost::thread _watcher
Notification thread.
Entry in the AlarmServerConnector statusmap.
void sendEMailNotification(const std::vector< AlarmStatusEntry > alarm)
Fire desktop notification.
static void switchOn() noexcept
Switch on red alarm flash light.
Definition: flashlight.cpp:64
Interface to the CMS (C++ Messaging Service) library of Apache ActiveMQ.
Send alarm notifications via e-mail.
Provide an opto-acoustic alarm notification on a control room PC.
Namespace for Alarm Notifications application.
static void sendAlarmNotification(const std::vector< AlarmStatusEntry > alarms) noexcept
Send an alarm notification via e-mail.
Definition: emailsender.cpp:53
Provides connectivity to the CSS Alarm Server.
size_t getNumberOfAlarms() const noexcept
Query number of active alarms.
#define noexcept
Allow using the noexcept keyword with GCC < 4.6.
Definition: oldgcccompat.h:52
time_t getTriggerTime() const noexcept
Query the trigger time.
const std::string & getSeverity() const noexcept
Query the severity.
unsigned int getDesktopNotificationTimeout() const noexcept
Timeout for sending a desktop notification.
Generic functions for exception handling.
AlarmServerConnector(const bool desktopVersion=false, const bool activateBeedo=false)
Constructor.
std::map< std::string, AlarmStatusEntry > _statusmap
Map of active alarms.
bool _runwatcher
Watcher thread abortion flag.
Singleton to read and change the configuration of this application.
static AlarmConfiguration & instance() noexcept
Get singleton instance.
void operateFlashLight()
Operate the red flashlight in the laboratory.
time_t _oldestAlarm
Timestamp of oldest alarm in _statusmap.
boost::thread _flashlightthread
Flashlight operation thread.
void checkStatusMap()
Check the _statusmap for pending notifications.