source: trunk/FACT++/src/evtserver.cc@ 19353

Last change on this file since 19353 was 19231, checked in by tbretz, 6 years ago
YYYYMMDD-1 does not always make sense ;)
File size: 11.1 KB
Line 
1#include <valarray>
2
3#include "Dim.h"
4#include "Event.h"
5#include "Shell.h"
6#include "StateMachineDim.h"
7#include "Connection.h"
8#include "Configuration.h"
9#include "Console.h"
10
11#include "tools.h"
12
13#include "LocalControl.h"
14
15#include "HeadersFAD.h"
16#include "HeadersEventServer.h"
17
18#include "fits.h"
19#include "nova.h"
20
21namespace ba = boost::asio;
22namespace bs = boost::system;
23
24using namespace std;
25
26// ------------------------------------------------------------------------
27
28#include "DimDescriptionService.h"
29#include "DimState.h"
30
31// ------------------------------------------------------------------------
32
33class StateMachineEventServer : public StateMachineDim
34{
35 DimDescribedState fDimFadControl;
36
37 string fAuxPath;
38 string fOutPath;
39 uint32_t fStartDate;
40 uint32_t fNight;
41 uint32_t fInterval;
42
43 fits *fIn;
44
45 uint32_t fQoS;
46 double fTime;
47 uint32_t fRun;
48 uint32_t fEvt;
49 //vector<float> fAvg;
50 //vector<float> fRms;
51 vector<float> fMax;
52 //vector<float> fPos;
53
54 Time fTimer;
55
56private:
57
58 int Execute()
59 {
60 if (GetCurrentState()==StateMachineImp::kSM_Ready)
61 return EventServer::State::kRunning;
62
63 // Nothing to do if not started
64 if (GetCurrentState()==EventServer::State::kIdle)
65 return EventServer::State::kIdle;
66
67 if (fDimFadControl.state()==FAD::State::kRunInProgress)
68 return EventServer::State::kStandby;
69
70 // Run only once in 5s
71 const Time now;
72 if (now<fTimer+boost::posix_time::milliseconds(fInterval))
73 return GetCurrentState();
74 fTimer = now;
75
76 // Running is only allowed when sun is up
77 const Nova::RstTime rst = Nova::GetSolarRst(now.JD()-0.5);
78 const bool isUp =
79 (rst.rise<rst.set && (now.JD()>rst.rise && now.JD()<rst.set)) ||
80 (rst.rise>rst.set && (now.JD()<rst.set || now.JD()>rst.rise));
81
82 // FIXME: What about errors?
83 if (!isUp)
84 return EventServer::State::kStandby;
85
86 // Check if file has to be changed
87 const uint32_t night = fStartDate>0 ? fStartDate : Time(Time().Mjd()-1).NightAsInt();
88
89 if (fNight!=night)
90 {
91 fNight = night;
92
93 delete fIn;
94
95 const string name = fAuxPath + Tools::Form("/%04d/%02d/%02d/%08d.FAD_CONTROL_EVENT_DATA.fits", night/10000, (night/100)%100, night%100, night);
96
97 fIn = new fits(name);
98 if (!fIn->is_open())
99 {
100 Error(string("Failed to open "+name+": ")+strerror(errno));
101 return StateMachineImp::kSM_Error;
102 }
103
104 // Requiered columns
105 try
106 {
107 fIn->SetRefAddress("QoS", fQoS);
108 fIn->SetRefAddress("Time", fTime);
109 fIn->SetVecAddress("max", fMax);
110 //fIn->SetVecAddress(fRms);
111 //fIn->SetVecAddress(fMax);
112 //fIn->SetVecAddress(fPos);
113 }
114 catch (const runtime_error &e)
115 {
116 delete fIn;
117 fIn = 0;
118
119 Error("Failed to open "+name+": "+e.what());
120 return StateMachineImp::kSM_Error;
121 }
122
123 // Non requiered columns
124 fRun = 0;
125 fEvt = 0;
126 try
127 {
128 fIn->SetRefAddress("run", fRun);
129 fIn->SetRefAddress("evt", fEvt);
130 }
131 catch (const runtime_error &e) { }
132
133 Info("File "+name+" open.");
134 }
135
136 if (GetCurrentState()==StateMachineImp::kSM_Error)
137 return StateMachineImp::kSM_Error;
138
139 // Get next data event
140 vector<float> sorted;
141 while (1)
142 {
143 if (!fIn->GetNextRow())
144 {
145 fNight = 0;
146 return EventServer::State::kRunning;
147 }
148
149 // Select a
150 if (fQoS & FAD::EventHeader::kAll)
151 continue;
152
153 for (int i=0; i<1440; i++)
154 fMax[i] /= 1000;
155
156 for (int i=8; i<1440; i+=9)
157 fMax[i] = fMax[i-2];
158
159 // construct output
160 sorted = fMax;
161 sort(sorted.begin(), sorted.end());
162
163 const double med = sorted[719];
164
165 vector<float> dev(1440);
166 for (int i=0; i<1440; i++)
167 dev[i] = fabs(sorted[i]-med);
168 sort(dev.begin(), dev.end());
169
170 const double deviation = dev[uint32_t(0.682689477208650697*1440)];
171
172 // In a typical shower or muon ring, the first
173 // few pixels will have comparable brightness,
174 // in a NSB event not. Therefore, the 4th brightest
175 // pixel is a good reference.
176 if (sorted[1439-3]>med+deviation*5)
177 break;
178 }
179
180 const double scale = max(0.25f, sorted[1436]);
181
182 ostringstream out;
183 out << Time(fTime+40587).JavaDate() << '\n';
184 out << "0\n";
185 out << scale << '\n';
186 out << setprecision(3);
187 if (fRun>0)
188 //out << "DEMO [" << fEvt << "]\nDEMO [" << fRun << "]\nDEMO\x7f";
189 out << fEvt << '\n' << fRun << "\nDEMO\x7f";
190 else
191 out << "DEMO\nDEMO\nDEMO\x7f";
192
193 //out << sorted[1439] << '\n';
194 //out << sorted[719] << '\n';
195 //out << sorted[0] << '\x7f';
196
197 // The valid range is from 1 to 127
198 // \0 is used to seperate different curves
199 vector<uint8_t> val(1440);
200 for (uint64_t i=0; i<1440; i++)
201 {
202 float range = nearbyint(126*fMax[i]/scale); // [-2V; 2V]
203 if (range>126)
204 range=126;
205 if (range<0)
206 range=0;
207 val[i] = (uint8_t)range;
208 }
209
210 const char *ptr = reinterpret_cast<char*>(val.data());
211 out.write(ptr, val.size()*sizeof(uint8_t));
212 out << '\x7f';
213
214 if (fOutPath=="-")
215 Out() << out.str();
216 else
217 ofstream(fOutPath+"/cam-fadcontrol-eventdata.bin") << out.str();
218
219 return EventServer::State::kRunning;
220 }
221
222 int StartServer()
223 {
224 fStartDate = 0;
225 return EventServer::State::kRunning;
226 }
227
228 int StopServer()
229 {
230 delete fIn;
231 fIn = 0;
232
233 return EventServer::State::kIdle;
234 }
235
236 int StartDate(const EventImp &evt)
237 {
238 fStartDate = evt.GetUInt();
239 return EventServer::State::kRunning;
240 }
241
242
243public:
244 StateMachineEventServer(ostream &out=cout) : StateMachineDim(out, "EVENT_SERVER"),
245 fDimFadControl("FAD_CONTROL"), fStartDate(0), fNight(0), fIn(0), fMax(1440)
246
247 {
248 fDimFadControl.Subscribe(*this);
249
250 // State names
251 AddStateName(EventServer::State::kIdle, "Idle",
252 "Event server stopped.");
253 AddStateName(EventServer::State::kRunning, "Running",
254 "Reading events file and writing to output.");
255 AddStateName(EventServer::State::kStandby, "Standby",
256 "No events are processed, either the sun is down or fadctrl in kRunInProgress.");
257
258
259 AddEvent("START", EventServer::State::kIdle, EventServer::State::kRunning, StateMachineImp::kSM_Error)
260 (bind(&StateMachineEventServer::StartServer, this))
261 ("Start serving the smartfact camera file");
262
263 AddEvent("START_DATE", "I:1", EventServer::State::kIdle, EventServer::State::kRunning, StateMachineImp::kSM_Error)
264 (bind(&StateMachineEventServer::StartDate, this, placeholders::_1))
265 ("Start serving the smartfact camera file with the events from the given date"
266 "|uint32[yyyymmdd]:Integer representing the date from which the data should be read");
267
268 AddEvent("STOP", EventServer::State::kRunning, EventServer::State::kStandby, StateMachineImp::kSM_Error)
269 (bind(&StateMachineEventServer::StopServer, this))
270 ("Stop serving the smartfact camera file");
271 }
272 ~StateMachineEventServer()
273 {
274 delete fIn;
275 }
276
277 int EvalOptions(Configuration &conf)
278 {
279 fAuxPath = conf.Get<string>("aux-path");
280 fOutPath = conf.Get<string>("out-path");
281 fInterval = conf.Get<uint32_t>("interval");
282
283 return -1;
284 }
285};
286
287// ------------------------------------------------------------------------
288
289#include "Main.h"
290
291template<class T>
292int RunShell(Configuration &conf)
293{
294 return Main::execute<T, StateMachineEventServer>(conf);
295}
296
297void SetupConfiguration(Configuration &conf)
298{
299 po::options_description control("Event server options");
300 control.add_options()
301 ("aux-path", var<string>("/fact/aux"), "The root path to the auxilary files.")
302 ("out-path", var<string>("www/smartfact/data"), "Path where the output camera file should be written.")
303 ("interval", var<uint32_t>(5000), "Interval of updates in milliseconds.")
304 ;
305
306 conf.AddOptions(control);
307}
308
309/*
310 Extract usage clause(s) [if any] for SYNOPSIS.
311 Translators: "Usage" and "or" here are patterns (regular expressions) which
312 are used to match the usage synopsis in program output. An example from cp
313 (GNU coreutils) which contains both strings:
314 Usage: cp [OPTION]... [-T] SOURCE DEST
315 or: cp [OPTION]... SOURCE... DIRECTORY
316 or: cp [OPTION]... -t DIRECTORY SOURCE...
317 */
318void PrintUsage()
319{
320 cout <<
321 "The event server copies events from fits files to the smartfact data.\n"
322 "\n"
323 "Usage: evtserver [-c type] [OPTIONS]\n"
324 " or: evtserver [OPTIONS]\n";
325 cout << endl;
326}
327
328void PrintHelp()
329{
330 Main::PrintHelp<StateMachineEventServer>();
331
332 /* Additional help text which is printed after the configuration
333 options goes here */
334
335 /*
336 cout << "bla bla bla" << endl << endl;
337 cout << endl;
338 cout << "Environment:" << endl;
339 cout << "environment" << endl;
340 cout << endl;
341 cout << "Examples:" << endl;
342 cout << "test exam" << endl;
343 cout << endl;
344 cout << "Files:" << endl;
345 cout << "files" << endl;
346 cout << endl;
347 */
348}
349
350int main(int argc, const char* argv[])
351{
352 Configuration conf(argv[0]);
353 conf.SetPrintUsage(PrintUsage);
354 Main::SetupConfiguration(conf);
355 SetupConfiguration(conf);
356
357 if (!conf.DoParse(argc, argv, PrintHelp))
358 return 127;
359
360 //try
361 {
362 // No console access at all
363 if (!conf.Has("console"))
364 {
365// if (conf.Get<bool>("no-dim"))
366// return RunShell<LocalStream, StateMachine, ConnectionFSC>(conf);
367// else
368 return RunShell<LocalStream>(conf);
369 }
370 // Cosole access w/ and w/o Dim
371/* if (conf.Get<bool>("no-dim"))
372 {
373 if (conf.Get<int>("console")==0)
374 return RunShell<LocalShell, StateMachine, ConnectionFSC>(conf);
375 else
376 return RunShell<LocalConsole, StateMachine, ConnectionFSC>(conf);
377 }
378 else
379*/ {
380 if (conf.Get<int>("console")==0)
381 return RunShell<LocalShell>(conf);
382 else
383 return RunShell<LocalConsole>(conf);
384 }
385 }
386 /*catch (std::exception& e)
387 {
388 cerr << "Exception: " << e.what() << endl;
389 return -1;
390 }*/
391
392 return 0;
393}
Note: See TracBrowser for help on using the repository browser.