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 }