282 lines
10 KiB
Python
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|