diff --git a/datalogger.py b/datalogger.py new file mode 100644 index 0000000..723566f --- /dev/null +++ b/datalogger.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python + +# -*- coding: utf-8 -*- + +import argparse, time, os, instruments, inspect + +#============================================================================== + +# Path +PATH = os.getcwd() +# Sampling time acquisition +SAMPLING_TIME = 1 +# File duration +FILE_DURATION = 3600*24 +# Default instrument +INSTRUMENT = None +# Default instrument adress +ADRESS = None +#Default val type +VAL_TYPE = None + +#============================================================================== + +def parse(): + """ + Specific parsing procedure for transfering data from any abstract instrument. + :returns: populated namespace (parser) + """ + + parser = argparse.ArgumentParser(description = 'Acquire data from INSTRUMENT', + epilog = 'Example: \'./datalogger.py -i myInstrument -st 10\' logs myInstrument every 10 seconds to output file YYYYMMDD-HHMMSS-INSTRUMENT.dat') + + parser.add_argument('-l', + action='store_true', + dest='list', + default=False, + help='List all available instruments') + + parser.add_argument('-I', + action='store', + dest='instLog', + default=INSTRUMENT, + help='Instrument to log (default '+str(INSTRUMENT)+')') + + parser.add_argument('-ip', + action='store', + dest='adress', + default=ADRESS, + help='Adress of instrument (IP, USB...) (default '+str(ADRESS)+')') + + parser.add_argument('-v', + action='store', + dest='vtype', + default=VAL_TYPE, + help='Value type to measure (default '+str(VAL_TYPE)+')') + + parser.add_argument('-st', + action='store', + dest='samplingtime', + default=SAMPLING_TIME, + help='Sampling time acquistion (default '+str(SAMPLING_TIME)+' second)') + + parser.add_argument('-fd', + action='store', + dest='fileduration', + default=FILE_DURATION, + help='File duration (infinite : \'-fd -1\') (default '+str(FILE_DURATION)+' second)') + + parser.add_argument('-p', + action='store', + dest='path', + default=PATH, + help='Absolute path (default '+PATH+')') + + args = parser.parse_args() + return args + +#============================================================================== + +def acq_routine(instrument, path, samplingtime, fileduration): + instrument.connect() + t0 = time.time() + filename = time.strftime("%Y%m%d-%H%M%S", time.gmtime(t0)) + '-' + instrument.model() + '.dat' + print('Opening %s' %filename) + try: + year = time.strftime("%Y", time.gmtime(t0)) + month = time.strftime("%Y-%m", time.gmtime(t0)) + os.chdir(path + '/' + year + '/' + month) + except: + try: + os.chdir(path + '/' + year) + os.mkdir(month) + os.chdir(path + '/' + year + '/' + month) + except: + os.chdir(path) + os.mkdir(year) + os.chdir(path + '/' + year) + os.mkdir(month) + os.chdir(path + '/' + year + '/' + month) + + data_file = open(filename, 'wr', 0) + + # Infinite loop + while True: + # tic + tic = time.time() + + if time.time() - t0 >= fileduration: + t0 = time.time() + print('Closing %s\n' %filename) + data_file.close() + + try: + year = time.strftime("%Y", time.gmtime(t0)) + month = time.strftime("%Y-%m", time.gmtime(t0)) + os.chdir(path + '/' + year + '/' + month) + except: + try: + os.chdir(path + '/' + year) + os.mkdir(month) + os.chdir(path + '/' + year + '/' + month) + except: + os.chdir(path) + os.mkdir(year) + os.chdir(path + '/' + year) + os.mkdir(month) + os.chdir(path + '/' + year + '/' + month) + + filename = time.strftime("%Y%m%d-%H%M%S", time.gmtime(t0)) + '-' + instrument.model() + '.dat' + print('Opening %s\n' %filename) + data_file = open(filename, 'wr', 0) + + try: + try: + #epoch time + epoch = time.time() + #MJD time + mjd = epoch / 86400.0 + 40587 + # Meas values + meas = instrument.getValue() + meas = meas.replace(",", "\t") + meas = meas.replace(";", "\t") + meas = meas.replace("+", "") + + string = "%f\t%f\t%s" % (epoch, mjd, meas) + data_file.write(string) # Write in a file + print(string) + + # Sleep until sampletime + time.sleep(samplingtime - (time.time() - tic)) + + except Exception as ex: + print 'Exception during controler data reading: ' + str(ex) + + except KeyboardInterrupt: + print '\n --> Disconnected' + instrument.disconnect() + data_file.close() + + # To stop the loop in a clean way + break + +#============================================================================== + +def main(): + """ + Main script + """ + # Parse command line + args = parse() + # path + path = args.path + # Sampling time + samplingtime=float(args.samplingtime) + # File duration + fileduration=int(args.fileduration) + # Instrument to log + instLog = args.instLog + # instrument adress + adress = args.adress + # val type + vtype = args.vtype + + try: + if args.list: + print('\nInstruments:') + for name, obj in inspect.getmembers(instruments): + if inspect.ismodule(obj) and name.startswith('__') == False and name.startswith('abstract') == False: + print('\n' + name) + exec('print("\t" + instruments.%s.ALL_VAL_TYPE)'%name) + + else: + if instLog == None: + raise Exception('No instrument selected !') + + if adress == None and vtype == None: + exec('myInstrument = instruments.%s.%s()'%(instLog, instLog)) + elif adress == None and vtype != None: + exec('myInstrument = instruments.%s.%s(vtype="%s")'%(instLog, instLog, vtype)) + elif adress != None and vtype != None: + exec('myInstrument = instruments.%s.%s(adress="%s", vtype="%s")'%(instLog, instLog, adress, vtype)) + acq_routine(myInstrument, path, samplingtime, fileduration) + + except Exception as ex: + print 'Oops: '+str(ex) + +#============================================================================== + +if __name__ == "__main__": + main()