Files
spaceballoon/datahandling.py
2015-11-18 20:35:48 -06:00

282 lines
10 KiB
Python

__author__ = 'asc'
import os
import datetime
from urllib import request, parse
import requests
import json
from cell_connection import initializeUartPort, baseOperations, initializeLogs
import logging
from requests_toolbelt import MultipartEncoder
import csv
import base64
SCRIPTDIR = os.path.dirname(os.path.abspath(__file__))
logger = logging.getLogger(__name__)
def add_keys_if_necessary(existing_file, test_dict):
all=None
try:
with open(existing_file,'r') as f:
reader = csv.reader(f)
header = []
try:
header = next(reader)
except StopIteration as e:
pass
if len(header) == 0:
header = list(test_dict.keys())
writer = csv.DictWriter(existing_file, test_dict.keys(), extrasaction='ignore')
writer.writeheader()
# if not header >= list(test_dict.keys()) or not header <= list(test_dict.keys()):
if len(set (header)-set(test_dict.keys()))>0:
existing_keys =set (header)
data_keys = set (test_dict.keys())
keys_to_add = data_keys - existing_keys
all = []
for key in keys_to_add:
header.append(key)
all.append(header)
for row in reader:
all.append(row)
pass
except (OSError, IOError, TypeError) as e:
header = list(test_dict.keys())
f=open(existing_file, 'a+')
writer = csv.DictWriter(f, test_dict.keys(), extrasaction='ignore')
writer.writeheader()
f.close()
if all is not None:
with open (existing_file, 'w') as f:
writer = csv.writer(f)
writer.writerows(all)
return header
class Datalogger():
def __init__(self,
missiontime,
text_path,
log_path,
photo_path):
self._mt = missiontime
self.text_path=text_path
self.log_path=os.path.join(log_path, 'MISSION {}.csv'.format(self._mt.name))
self.photo_path=photo_path
pass
def log(self, r):
self._record = r._get_dict()
# logger.info('Recording {}'.format(self._record))
for k in self._record.keys():
if k is 'b':
if self._record[k] is not list:
l = [self._record[k]]
else:
l = self._record[k]
for item in l:
logger.debug("item: {}".format(self._record), extra={'MISSION_TIME': self._mt.now(), 'MISSION_ID':self._mt.name})
item['at']=self._mt.to_absolutetime(item['mt'])
item['mid']=self._mt.name
header = add_keys_if_necessary(self.log_path, item)
keys = header
log=open(self.log_path, 'a')
writer = csv.DictWriter(log, keys, extrasaction='ignore')
writer.writerow(item)
log.close()
logger.info('Barometer data recorded',extra={'MISSION_TIME': self._mt.now(), 'MISSION_ID':self._mt.name})
elif k is 'i':
if self._record[k] is tuple:
l = [self._record[k]]
else:
l = self._record[k]
for item in l:
# Form is ('name', file object, 'type')
filename = item[0]
file = base64.b64decode(bytes(item[1],'ascii'))
folder = os.path.join(self.photo_path, self._mt.mid)
file_path = os.path.join(self.photo_path, folder, filename)
if not os.path.exists(folder):
os.makedirs(folder)
with open(file_path, 'wb') as f:
f.write(file)
# file.save(os.path.join(self.photo_path, filename))
logger.info('Image data recorded',extra={'MISSION_TIME': self._mt.now(), 'MISSION_ID':self._mt.name})
return 'success'
class Datareporter():
from lib.sim900.inetgsm import SimInetGSM
def __init__(self,
missiontime,
url,
data_path,
image_path,
ping_path,
server_port,
com_port_name=None,
baud_rate=None,
use_lan = False,
path=SCRIPTDIR):
#TODO communication
self.mt = missiontime
self.url = url
self.server_port=server_port
self.image_path = image_path
self.data_path = data_path
self.com_port_name = com_port_name
self.baud_rate = baud_rate
self.ping_path = ping_path
self.use_lan = use_lan
self._transpondence=None
if not use_lan:
self.port = initializeUartPort(portName=self.com_port_name, baudrate=self.baud_rate)
d = baseOperations(self.port, logger)
if not d is None:
(self.gsm, self.imei) = d
self.inet = self.SimInetGSM(self.port, logger)
logger.info('ip = {0}'.format(self.inet.ip), extra={'MISSION_TIME': self.mt.now(), 'MISSION_ID':self.mt.name})
logger.debug('attaching GPRS', extra={'MISSION_TIME': self.mt.now(), 'MISSION_ID':self.mt.name})
if not self.inet.attachGPRS('wholesale', '', '', 1):
logger.error('error attaching GPRS', extra={'MISSION_TIME': self.mt.now(), 'MISSION_ID':self.mt.name})
return False
#register mission number to server
intiate = Record(str(self.mt.timezero),'zt')
# intiate.add(self.mt.mid,'mid')
self.send(intiate, _intiating_report=True)
@property
def status (self):
#TODO status check
try:
return (0, 'Data reporter functioning properly')
except Exception as e:
return (1, 'Data reporter error: %s' % e)
def _send_data(self, message, _intiating_report=False):
response=None
m = MultipartEncoder(fields=message)
if _intiating_report:
path = '{0}'.format(self.image_path)
else:
path = '{0}/{1}'.format(self.image_path,self.mt.mid)
if self.use_lan:
logger.info ('Sending transpondence using LAN', extra={'MISSION_TIME': self.mt.now(), 'MISSION_ID':self.mt.name})
response = requests.post('{0}:{1}/{2}'.format(self.url, self.server_port, path), data=m.read(), headers={'Content-Type': m.content_type})
pass
elif not self.use_lan:
logger.info ('Sending transpondence using modem', extra={'MISSION_TIME': self.mt.now(), 'MISSION_ID':self.mt.name})
# logger.debug('attaching GPRS')
# if not self.inet.attachGPRS('wholesale', '', '', 1):
# logger.error('error attaching GPRS')
# return False
logger.debug('ip = {0}'.format(self.inet.ip), extra={'MISSION_TIME': self.mt.now(), 'MISSION_ID':self.mt.name})
logger.debug('making HTTP POST request', extra={'MISSION_TIME': self.mt.now(), 'MISSION_ID':self.mt.name})
if not self.inet.httpPOST(
self.url,
self.server_port,
"/{}".format(path),
m.to_string(),
contentType=m.content_type
):
logger.error('error making HTTP POST: {0}'.format(self.inet.errorText), extra={'MISSION_TIME': self.mt.now(), 'MISSION_ID':self.mt.name})
return False
if self.inet.httpResponse is not None:
response = str(self.inet.httpResponse).replace('\n\r', '\n')
else:
response = 'empty response'
if _intiating_report:
if type (response) is str:
mid = response
else:
mid = response.text
self.mt.set_mid(mid)
return response
def send(self, t, _intiating_report=False):
self._transpondence = t._get_dict()
self._transpondence['mt'] = self.mt.now()
# print ('Send transpondence {}'.format(self._transpondence))
for k in self._transpondence.keys():
# if self._transpondence[k] is list or self._transpondence[k] is dict or self._transpondence[k] is float:
if type(self._transpondence) is dict:
self._transpondence[k] = json.dumps(self._transpondence[k])
r = self._send_data(message=self._transpondence, _intiating_report=_intiating_report)
#On error, do not clear transpondence
if not r:
self._transpondence = self._transpondence
return None
class Record():
def __init__(self,first_item=None, first_item_type=None):
# if self._transpondence is None:
self._transpondence={}
if first_item and first_item_type:
self.add(first_item, first_item_type)
def add(self, data, info_type='data'):
if type(data) is not list:
if self._transpondence.get(info_type) is not None:
if type(self._transpondence.get(info_type)) is list:
self._transpondence[info_type].append(data)
else:
self._transpondence[info_type] = [self._transpondence[info_type]]
self._transpondence[info_type].append(data)
else:
self._transpondence[info_type]=data
else:
if self._transpondence.get(info_type) is not None:
if type(self._transpondence.get(info_type)) is list:
self._transpondence[info_type] + data
else:
self._transpondence[info_type] = [self._transpondence[info_type]]
self._transpondence[info_type] + data
else:
self._transpondence[info_type]=data
def _get_dict(self):
return self._transpondence