tr_position.py 8.8 KB
#!/usr/bin/env python
#! python

"""
	SPOT position recovery from internet.
	Positions are also flagged if they are in water/land or onboard

"""

import sys
import xml.dom.minidom as minidom
import urllib
import math
import csv
import fiona
import pandas as pd
import shapely.geometry
from time import localtime, strftime, ctime

# debug pour le protocole ssl
import ssl
from functools import wraps
def sslwrap(func):
	@wraps(func)
	def bar(*args, **kw):
		kw['ssl_version'] = ssl.PROTOCOL_TLSv1
		return func(*args, **kw)
	return bar

ssl.wrap_socket = sslwrap(ssl.wrap_socket)

#==================================================
#Liste globale contenant tous les objets 
#instancies a partir de la classe Spot
#==================================================

spots = []

class Spot:
	"""
	Classe pour les GPS SPOT 
	"""
	spotCount=0
	rayonTerre = 6371.0 # Rayon moyen  de la terre

	distancePlusPres = 100000000.0 # Init a 1 million de km !
	capPlusPres = 0.0
	identPlusPres = 0
	parentPlusPres = 0
	ecartDistance = 0
	
	spotPlusPres = None
	dejaTraite  = False

	def __init__(self,esnName):
		self.esnName = esnName
		Spot.spotCount += 1

	def setEsn(self,esn):
		self.esn = esn
	
	def setTimestamp(self, timestamp):
		self.timestamp = timestamp

	def setTimeGMT(self, timeGMT):
		self.timeGMT = int(timeGMT)

	def setTimeStampEST(self, timeGMT):
		self.timeStampEST = ctime(int(timeGMT))

	def setLatitude(self,latitude):
		self.latitude = float(latitude)
		
	def setLongitude(self, longitude):
		self.longitude = float(longitude)

	def setMessageType(self, messagetype):
		self.messagetype = messagetype
		
	def setFlag(self, flag):
		self.flag = flag
		
		

#############################################################
#
#Lecture du fichier XML contenant les information des spots et
#Instanciation de tous les objets Spot a partir de ces info.
#
#A la sortie de cette fonction, la liste globale spots[] contient
#tous les spots necessaires au traitement
#
#############################################################

def getTags(url):
	"""
	Initialiser tous les spots a partir du fichier XML
	"""

	doc = minidom.parse(urllib.urlopen(url))
	node = doc.documentElement
	messages = doc.getElementsByTagName("message")

# Initialisation des listes de donnes

	esns = []
	esnNames = []
	timestamps = []
	timeInGMTSeconds = []
	latitudes = []
	longitudes = []
	messagetype = []
	spottemp = []

# On boucle sur tous les tags messages du fichier XML
# et on extrait les informations

	if len(messages) == 0:
		sys.exit(1)

	for message in messages:
		esnObj = message.getElementsByTagName("messengerId")[0]
		esns.append(esnObj)
		esnNameObj = message.getElementsByTagName("messengerName")[0]
		esnNames.append(esnNameObj)
		timestampObj = message.getElementsByTagName("dateTime")[0]
		timestamps.append(timestampObj)
		timeGMTObj = message.getElementsByTagName("unixTime")[0]
		timeInGMTSeconds.append(timeGMTObj)
		latObj = message.getElementsByTagName("latitude")[0]
		latitudes.append(latObj)
		lonObj = message.getElementsByTagName("longitude")[0]
		longitudes.append(lonObj)
		msgtypeObj = message.getElementsByTagName("messageType")[0]
		messagetype.append(msgtypeObj)


#On instancie une liste temporaire d'objets de classe Spot
#qui contient l'information de tous les spots 
	for esnName in esnNames:
		nodes = esnName.childNodes
		for node in nodes:
			spottemp.append(Spot(node.data))

#On conserve l'info dans chaque objet

	for i,s  in enumerate(spottemp):
		nodes = esns[i].childNodes
		for node in nodes:
			s.setEsn(node.data)
		nodes = timestamps[i].childNodes
		for node in nodes:
			s.setTimestamp(node.data)
		nodes = timeInGMTSeconds[i].childNodes
		for node in nodes:
			s.setTimeGMT(node.data)
			s.setTimeStampEST(node.data)
		nodes = latitudes[i].childNodes
		for node in nodes:
			s.setLatitude(node.data)
		nodes = longitudes[i].childNodes
		for node in nodes:
			s.setLongitude(node.data)
		nodes = messagetype[i].childNodes
		for node in nodes:
			s.setMessageType(node.data)

#
#On produit une liste unique des identifiants des spots 
#
	spotlist = sorted(set([s.esnName for s in spottemp ]))

#
#On boucle sur la liste des identifiants uniques
#et pour chaque spot on conserve la donnee la plus recente
#(max timestamp)
#
	for i in spotlist :
		spotmax = None
		for s in spottemp :
			if s.esnName == i:
				if spotmax == None:
					spotmax = s
				if int(s.timeGMT) > int(spotmax.timeGMT) :
					spotmax = s

		spots.append(spotmax)

#
#Rendu ici, la liste spots contient une entree par spot
#et cette entree est la plus recente (plus grand timestamp)
# Fin de la fonction
#

############################################################
#
#	implemente les positions des spots dans le csv
#
############################################################

def ecrirecsv(fichier) :
	""" 
	Creation of a temporary csv file from SPOT class 
	"""

	# cree un fichier temporaire de spots_pos
	f = open(fichier, "w")
	writer = csv.writer(f,delimiter=';')
	writer.writerow(['SPOT','LAT','LON','TIME','STATUS','FLAG'])
	
	for k in spots:
		
		k.flag = "FLG"
		data = [ str(k.esnName), float(k.latitude), float(k.longitude),\
				 int(k.timeGMT), str(k.messagetype), str(k.flag)]
		writer.writerow(data)   
	f.close
	
def cleancsv(fichier_clean) :
	"""
	Nettoyage du csv (suppression des doublons)
	"""

	# nettoyage des doublons 
	with open('/share/archives/partage_lasso/spot/spots_pos_flag.csv','r') as in_file,\
	 open(fichier_clean,'w') as out_file:
		 seen = set() 
		 for line in in_file:
			 if line in seen: continue # skip duplicate
			 seen.add(line)
			 out_file.write(line)

def flagcsv(fichier_flag) :
	"""
	marquage des positions
	"""

	# lit le fichier des positions flaguees
	df = pd.read_csv(fichier_flag,delimiter=';')
	df = df.drop_duplicates(take_last=True)	
	
	# lit le fichier des dernieres positions crees dans 'ecrirecsv'
	tmp = pd.read_csv('/share/archives/partage_lasso/spot/tmp.csv',delimiter=';')
	
	# charge le shapefile du trait de cote du GSL
	s = fiona.open("/share/archives/nicp0003/spot/shp/GSL_GSHHS_f.shp")
	shapefile_record = s.next()
	shape = shapely.geometry.asShape(shapefile_record['geometry'])
	x_min, y_min, x_max, y_max = shape.bounds
	rayonTerre = 6371.0
	
	# 
	for index,val in tmp.iterrows():
		LON = val['LON']
		LAT = val['LAT']
		T   = val['TIME']
		SPT = val['SPOT']
		STA = val['STATUS']
		
		# avant-dernieres positions des spots
		T1   = df.loc[(df['SPOT'] == SPT)\
				  & (df['TIME'] < T), 'TIME'][-1:].values
		
		LAT1 = df.loc[(df['SPOT'] == SPT)\
				  & ((df['TIME'] < T)), 'LAT'][-1:].values
				  
		LON1 = df.loc[(df['SPOT'] == SPT)\
				  & ((df['TIME'] < T)), 'LON'][-1:].values
		
		
		if not LAT1:
			LAT1 = LAT	
		if not LON1:
			LON1 = LON	
		if not T1:
			T1 = T	
			
		lat1 = math.radians(LAT)
		lon1 = math.radians(LON)
		tim1 = T
		lat2 = math.radians(LAT1)
		lon2 = math.radians(LON1)
		tim2 = T1
		dlat = math.radians(LAT1 - LAT)
		dlon = math.fabs(math.radians(LON1 - LON))
		
		dPhi = math.log(math.tan(lat2/2+math.pi/4)/math.tan(lat1/2+math.pi/4))
	
		if dPhi <> 0 :
			q = dlat/dPhi
		else :
			q = math.cos(lat1)
	
		#if dLon > 180 degres take shorter rhumb across anti-meridian:
		if math.fabs(dlon) > math.pi :
			if dlon > 0 :
				dlon= -(2*math.pi - dlon) 
			else: 
				dlon = (2*math.pi + dlon)
	
		dist = math.sqrt(dlat*dlat + q*q*dlon*dlon) * rayonTerre
		
		# si distance non nulle (s'il y a une position anterieur du spot)
		# calcul de la vitesse par rapport a la derniere position connue
		if not dist == 0:
			vitesse = (dist * 1000) / abs((tim2 - tim1))  # m.s-1
			# si vitesse > 1.1 m.s (sur bateau par exemple)
			if vitesse > 1.1:
				val.FLAG = "SPD"
			else:
				val.FLAG = "OCN"
		
		# si distance nulle =  marque "NEW"
		if dist == 0:
			val.FLAG = "NEW"
		
		# si position a l'interieur du trait de cote = marque "LND"
		point = shapely.geometry.Point(LON,LAT)
		if shape.contains(point):
				val.FLAG = "LND"

		# si LON / LAT incoherent = marque "OUT"
		if (LON < x_min) or (LON > x_max) \
		or (LAT < y_min) or (LAT > y_max):
				val.FLAG = "OUT"
		
		# rajoute les positions flaguees au fichier final
		f = open(fichier_flag, "ab")
		writer = csv.writer(f,delimiter=';',lineterminator="\n")
		data = [ str(SPT), float(round(LAT,6)), float(round(LON,6)), int(T), str(STA), str(val.FLAG)]
		writer.writerow(data)
		f.close
	

#############################################################
#
#	Debut du programme principal
#
#############################################################

if __name__ == "__main__":
#	url = ' http://share.findmespot.com/messageService/guestlinkservlet?glId=03kp21oFnOj8bRHaPQPPAjf2TuO19VRa3'
	url = ' https://api.findmespot.com/spot-main-web/consumer/rest-api/2.0/public/feed/0zgtS2Yrxgzl8in5LvVoAg0ae76LfQcdO/message.xml'
	getTags(url)

ecrirecsv("/share/archives/partage_lasso/spot/tmp.csv")
flagcsv("/share/archives/partage_lasso/spot/spots_pos_flag.csv")
cleancsv("/share/archives/partage_lasso/spot/spots_pos_flag_clean.csv")

sys.exit(0)