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

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