forked from tybtab/dosenet-raspberrypi
/
manager_D3S.py
338 lines (281 loc) · 11.2 KB
/
manager_D3S.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
import time
import traceback
from globalvalues import RPI
if RPI:
import RPi.GPIO as GPIO
from auxiliaries import Config, PublicKey, LED
from globalvalues import POWER_LED_PIN, NETWORK_LED_PIN
from auxiliaries import datetime_from_epoch, set_verbosity
from sender import ServerSender
from data_handler_d3s import Data_Handler_D3S
from globalvalues import DEFAULT_CONFIG, DEFAULT_PUBLICKEY, DEFAULT_LOGFILE_D3S
from globalvalues import DEFAULT_HOSTNAME, DEFAULT_UDP_PORT, DEFAULT_TCP_PORT
from globalvalues import DEFAULT_SENDER_MODE
from globalvalues import DEFAULT_DATALOG_D3S
import argparse
import kromek
import numpy as np
import time
from globalvalues import DEFAULT_INTERVAL_NORMAL_D3S
from globalvalues import DEFAULT_INTERVAL_TEST_D3S
from auxiliaries import set_verbosity
import signal
import sys
def signal_term_handler(signal, frame):
# If SIGTERM signal is intercepted, the SystemExit exception routines
# get run
print 'Got Sigterm!'
sys.exit(0)
signal.signal(signal.SIGTERM, signal_term_handler)
class Manager_D3S(object):
"""
Master object for D3S device operation.
Prints out spectra for every interval, stores each spectra, and sums the spectra together.
Interval is in seconds with the default being 30 seconds.
"""
def __init__(self,
interval=None,
count=0,
transport='any',
device='all',
log_bytes=False,
verbosity=None,
datalog=None,
datalogflag=False,
test=None,
config=None,
publickey=None,
hostname=DEFAULT_HOSTNAME,
port=None,
sender_mode=DEFAULT_SENDER_MODE,
logfile=None,
log=False,
running=False,
network_LED_pin=NETWORK_LED_PIN,
power_LED_pin=POWER_LED_PIN,
):
self.running = running
self.total = None
self.lst = None
self.create_structures = True
self.interval = interval
self.count = count
self.transport = transport
self.device = device
self.log_bytes = log_bytes
self.datalog = datalog
self.datalogflag = datalogflag
self.a_flag()
self.d_flag()
self.make_data_log(self.datalog)
self.test = test
self.handle_input(log, logfile, verbosity, interval, config, publickey)
if RPI:
self.power_LED = LED(power_LED_pin)
self.network_LED = LED(network_LED_pin)
self.power_LED.on()
else:
self.power_LED = None
self.network_LED = None
self.data_handler = Data_Handler_D3S(
manager=self,
verbosity=self.v,
logfile=self.logfile,
network_led=self.network_LED)
self.sender = ServerSender(
manager=self,
mode=sender_mode,
port=port,
verbosity=self.v,
logfile=self.logfile,)
# DEFAULT_UDP_PORT and DEFAULT_TCP_PORT are assigned in sender
self.data_handler.backlog_to_queue()
def a_flag(self):
"""
Checks if the -a from_argparse is called.
If it is called, sets the path of the data-log to
DEFAULT_DATALOG.
"""
if self.datalogflag:
self.datalog = DEFAULT_DATALOG_D3S
def d_flag(self):
"""
Checks if the -d from_argparse is called.
If it is called, sets datalogflag to True.
"""
if self.datalog:
self.datalogflag = True
def make_data_log(self, file):
if self.datalogflag:
with open(file, 'a') as f:
pass
def handle_input(self, log, logfile, verbosity, interval, config, publickey):
"""
Sets up logging, verbosity, interval, config, and publickey
"""
# resolve logging defaults
if log and logfile is None:
# use default file if logging is enabled
logfile = DEFAULT_LOGFILE_D3S
if logfile and not log:
# enable logging if logfile is specified
# (this overrides a log=False input which wouldn't make sense)
log = True
if log:
self.logfile = logfile
else:
self.logfile = None
if verbosity is None:
verbosity = 1
self.v = verbosity
set_verbosity(self, logfile=logfile)
if log:
self.vprint(1, '')
self.vprint(1, 'Writing to logfile at {}'.format(self.logfile))
self.running = True
if interval is None:
self.vprint(
2, "No interval given, using interval at 30 seconds")
interval = DEFAULT_INTERVAL_NORMAL_D3S
if config is None:
self.vprint(2, "No config file given, " +
"attempting to use default config path")
config = DEFAULT_CONFIG
if publickey is None:
self.vprint(2, "No publickey file given, " +
"attempting to use default publickey path")
publickey = DEFAULT_PUBLICKEY
self.interval = interval
if config:
try:
self.config = Config(config,
verbosity=self.v, logfile=self.logfile)
except IOError:
raise IOError(
'Unable to open config file {}!'.format(config))
else:
self.vprint(
1, 'WARNING: no config file given. Not posting to server')
self.config = None
if publickey:
try:
self.publickey = PublicKey(
publickey, verbosity=self.v, logfile=self.logfile)
except IOError:
raise IOError(
'Unable to load publickey file {}!'.format(publickey))
else:
self.vprint(
1, 'WARNING: no public key given. Not posting to server')
self.publickey = None
def run(self):
"""
Main method. Currently also stores and sum the spectra as well.
Current way to stop is only using a keyboard interrupt.
"""
if self.transport == 'any':
devs = kromek.discover()
else:
devs = kromek.discover(self.transport)
print 'Discovered %s' % devs
if len(devs) <= 0:
return
filtered = []
for dev in devs:
if self.device == 'all' or dev[0] in self.device:
filtered.append(dev)
devs = filtered
if len(devs) <= 0:
return
done_devices = set()
try:
while self.running:
with kromek.Controller(devs, self.interval) as controller:
for reading in controller.read():
if self.create_structures:
self.total = np.array(reading[4])
self.lst = np.array([reading[4]])
self.create_structures = False
else:
self.total += np.array(reading[4])
self.lst = np.concatenate((self.lst, [np.array(reading[4])]))
serial = reading[0]
dev_count = reading[1]
if serial not in done_devices:
this_start, this_end = self.get_interval(
time.time() - self.interval)
self.handle_spectra(this_start, this_end, reading[4])
if dev_count >= self.count > 0:
done_devices.add(serial)
controller.stop_collector(serial)
if len(done_devices) >= len(devs):
break
except KeyboardInterrupt:
self.vprint(1, '\nKeyboardInterrupt: stopping Manager run')
self.takedown()
except SystemExit:
self.vprint(1, '\nSystemExit: taking down Manager')
self.takedown()
def get_interval(self, start_time):
"""
Return start and end time for interval, based on given start_time.
"""
end_time = start_time + self.interval
return start_time, end_time
def data_log(self, file, spectra):
"""
Writes spectra to data-log.
"""
if self.datalogflag:
with open(file, 'a') as f:
f.write('{0}, '.format(spectra))
self.vprint(2, 'Writing spectra to data log at {}'.format(file))
def handle_spectra(self, this_start, this_end, spectra):
"""
Get spectra from sensor, display text, send to server.
"""
self.data_handler.main(
self.datalog, spectra, this_start, this_end)
def takedown(self):
"""
Sets self.running to False and deletes self. Also turns off LEDs
"""
self.power_LED.off()
GPIO.cleanup()
self.running = False
self.data_handler.send_all_to_backlog()
del(self)
@classmethod
def from_argparse(cls):
parser = argparse.ArgumentParser()
parser.add_argument('--hostname', '-s', default=DEFAULT_HOSTNAME)
parser.add_argument('--port', '-p', type=int, default=None)
parser.add_argument('--sender-mode', '-m', type=str, default=DEFAULT_SENDER_MODE, choices=['udp', 'tcp', 'UDP', 'TCP'])
parser.add_argument('--config', '-c', default=None)
parser.add_argument('--datalog', '-d', default=None)
parser.add_argument('--datalogflag', '-a', action='store_true', default=False)
parser.add_argument('--publickey', '-k', default=None)
parser.add_argument('--verbosity', '-v', type=int, default=None)
parser.add_argument('--test', '-t', action='store_true', default=False)
parser.add_argument('--transport', '-n', default='any')
parser.add_argument('--interval', '-i', type=int, default=None)
parser.add_argument('--count', '-0', dest='count', default=0)
parser.add_argument('--device', '-e', dest='device', default='all')
parser.add_argument('--log-bytes', '-b', dest='log_bytes', default=False, action='store_true')
parser.add_argument('--log', '-l', action='store_true', default=False)
parser.add_argument('--logfile', '-f', type=str, default=None)
args = parser.parse_args()
arg_dict = vars(args)
mgr = Manager_D3S(**arg_dict)
return mgr
if __name__ == '__main__':
mgr = Manager_D3S.from_argparse()
try:
mgr.run()
except:
if mgr.logfile:
# print exception info to logfile
with open(mgr.logfile, 'a') as f:
traceback.print_exc(15, f)
# regardless, re-raise the error which will print to stderr
raise