Repository URL to install this package:
|
Version:
0.2.1 ▾
|
#!/usr/bin/env python
# GeoJSON data handler
#
# This class queries the GEOMAR GeoServer for updates of connected platforms. Uses a JSON-file to store data
#
# TODO: Mapping of properties should be configurable
# TODO: Fix Course over ground
# TODO: Add description to platform output (for use in log)
#
# Copyright (c) 2019 GEOMAR Helmholtz Centre for Ocean Research Kiel
#
# Author: Patrick Leibold
# Last change: 2019-10-20
import os
#import urllib.request
import requests
import geojson
import json
import logging
import calendar
from iso8601 import parse_date
class DataHandler:
"""
Very simple and straightforward data handler to retrieve
and store GeoJSON data from maps.geomar.de/geoserver
"""
# Class variables
__config = {}
__data_url = ""
__platformlist_file = ""
__platforms = {}
__updates = {}
def __init__(self, config):
"""Class constructor"""
self.__config = config
self.__data_url = self.__config["General"]["GeoJsonUrl"]
# enable overwriting platforms file location by environment variable
self.__platformlist_file = os.environ.get('SAILDRONE_PLATFORMS_LIST_FILE') \
or self.__config["General"]["PlatformsListFileName"]
logging.info("Data handler initialized")
def get_all_platforms(self):
"""Returns all downloaded platforms"""
return self.__platforms
def get_updated_platforms(self):
"""Returns only updated platforms since the last server call"""
return self.__updates
def try_load(self):
"""Tries to load new GeoJSON data from the Geoserver"""
if self.__data_url == "":
return
# Empty list of updates
self.__updates = {}
# Load geoJSON data from server
with requests.get(self.__data_url) as response:
collection = response.json()
# Read platform list from file or create if not existing
if not os.path.exists(self.__platformlist_file):
with open(self.__platformlist_file, 'w') as outfile:
outfile.write("{}")
else:
with open(self.__platformlist_file, 'r') as infile:
self.__platforms = json.load(infile)
for feature in collection['features']:
key = str(feature['properties']["platform_id"])
# Convert ISO timestamp to UNIX timestamp
timestamp = self.__convert_timestamp(feature['properties']["obs_timestamp"])
# Update platforms
if key in self.__platforms:
platform = self.__platforms[key]
if platform["timestamp"] != timestamp:
# Update platform
platform["timestamp"] = timestamp
platform["latitude"] = feature['geometry']['coordinates'][1]
platform["longitude"] = feature['geometry']['coordinates'][0]
platform["speed_over_ground"] = self.__handle_null(feature['properties']["speed_over_ground"])
platform["course_over_ground"] = self.__handle_null(feature['properties']["heading"]) # FIXME
platform["heading"] = self.__handle_null(feature['properties']["heading"])
# Add platform to updated items
self.__updates[key] = platform
else:
# Create new platform
platform = {
"timestamp": timestamp,
"latitude": feature['geometry']['coordinates'][1],
"longitude": feature['geometry']['coordinates'][0],
"speed_over_ground": self.__handle_null(feature['properties']["speed_over_ground"]),
"course_over_ground": self.__handle_null(feature['properties']["heading"]), # FIXME
"heading": self.__handle_null(feature['properties']["heading"]),
"enabled": True
}
# Add platform to updated items
self.__updates[key] = platform
# Add platform to list
self.__platforms[key] = platform
# If there are updated platforms: Write platform list back to file
if len(self.__updates.keys()) > 0:
self.__dump_platforms()
def __dump_platforms(self):
"""Writes platform list to file"""
with open(self.__platformlist_file, 'w') as outfile:
json.dump(self.__platforms, outfile, sort_keys=False)
@staticmethod
def __convert_timestamp(obs_timestamp):
"""Converts timestamp supplied by Geoserver to format expected by Saildrone API
:param obs_timestamp Timestamp in ISO Format as supplied by Geoserver
:returns POSIX timestamp to be used in Saildrone API
"""
parsed = parse_date(obs_timestamp.replace("Z", "+00:00"))
timestamp = int(calendar.timegm(parsed.timetuple()))
# alternative: timestamp = parsed.timestamp()
return timestamp
@staticmethod
def __handle_null(value):
"""Converts JSON null to number"""
if value is None:
return 0
return value