tr_position.py 8.8 KB
Newer Older
1 2 3
#!/usr/bin/env python
#! python

4 5 6 7 8 9
"""
	SPOT position recovery from internet.
	Positions are also flagged if they are in water/land or onboard

"""

10 11 12 13 14 15
import sys
import xml.dom.minidom as minidom
import urllib
import math
import csv
import fiona
16
import pandas as pd
17 18 19
import shapely.geometry
from time import localtime, strftime, ctime

20 21 22 23 24 25 26 27 28 29 30 31 32
# 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)

#==================================================
33 34
#Liste globale contenant tous les objets 
#instancies a partir de la classe Spot
35
#==================================================
36

37
spots = []
38 39

class Spot:
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
	"""
	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):
81
		self.flag = flag
82 83
		
		
84 85 86 87 88 89

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

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

100 101 102
	doc = minidom.parse(urllib.urlopen(url))
	node = doc.documentElement
	messages = doc.getElementsByTagName("message")
103 104 105

# Initialisation des listes de donnes

106 107 108 109 110 111 112 113
	esns = []
	esnNames = []
	timestamps = []
	timeInGMTSeconds = []
	latitudes = []
	longitudes = []
	messagetype = []
	spottemp = []
114 115 116 117

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

118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
	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)
136 137 138 139


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

#On conserve l'info dans chaque objet

147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
	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)
167 168 169 170

#
#On produit une liste unique des identifiants des spots 
#
171
	spotlist = sorted(set([s.esnName for s in spottemp ]))
172 173 174 175 176 177

#
#On boucle sur la liste des identifiants uniques
#et pour chaque spot on conserve la donnee la plus recente
#(max timestamp)
#
178 179 180 181 182 183 184 185
	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
186

187
		spots.append(spotmax)
188 189 190 191 192 193 194 195 196

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

############################################################
#
197
#	implemente les positions des spots dans le csv
198 199 200 201
#
############################################################

def ecrirecsv(fichier) :
202 203 204 205 206 207
	""" 
	Creation of a temporary csv file from SPOT class 
	"""

	# cree un fichier temporaire de spots_pos
	f = open(fichier, "w")
208
	writer = csv.writer(f,delimiter=';')
209
	writer.writerow(['SPOT','LAT','LON','TIME','STATUS','FLAG'])
210 211 212
	
	for k in spots:
		
213 214 215 216
		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)   
217 218
	f.close
	
219
def cleancsv(fichier_clean) :
220 221 222 223
	"""
	Nettoyage du csv (suppression des doublons)
	"""

224
	# nettoyage des doublons 
225
	with open('/share/archives/partage_lasso/spot/spots_pos_flag.csv','r') as in_file,\
226 227 228 229 230 231 232
	 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)

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
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
	
334 335 336

#############################################################
#
337
#	Debut du programme principal
338 339 340 341
#
#############################################################

if __name__ == "__main__":
342 343 344
#	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)
345

346 347 348
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")
349 350

sys.exit(0)