sondehub-infra/predict/lambda_function.py

178 lines
5.5 KiB
Python
Raw Normal View History

2021-02-22 06:13:30 +00:00
import boto3
import botocore.credentials
from botocore.awsrequest import AWSRequest
from botocore.endpoint import URLLib3Session
from botocore.auth import SigV4Auth
import json
import os
from datetime import datetime, timedelta, timezone
2021-09-13 05:41:23 +00:00
import sys
import traceback
2021-02-22 06:13:30 +00:00
import http.client
2021-03-22 09:25:58 +00:00
import math
2021-04-04 00:47:31 +00:00
import logging
import gzip
from io import BytesIO
2021-09-17 13:50:36 +00:00
import base64
2021-02-22 06:13:30 +00:00
HOST = os.getenv("ES")
2021-04-04 00:47:31 +00:00
2021-02-22 06:13:30 +00:00
def predict(event, context):
2021-09-13 05:41:23 +00:00
path = "predictions-*/_search"
2021-02-22 06:13:30 +00:00
payload = {
2021-09-13 05:41:23 +00:00
"aggs": {
"2": {
"terms": {
"field": "serial.keyword",
"order": {
2021-02-22 06:13:30 +00:00
"_key": "desc"
},
2021-09-13 05:41:23 +00:00
"size": 1000
},
"aggs": {
"1": {
"top_hits": {
"_source": True,
"size": 1,
"sort": [
2021-02-22 06:13:30 +00:00
{
"datetime": {
2021-09-13 05:41:23 +00:00
"order": "desc"
2021-02-22 06:13:30 +00:00
}
}
2021-09-13 05:41:23 +00:00
]
2021-02-22 06:13:30 +00:00
}
}
2021-09-13 05:41:23 +00:00
}
}
},
"size": 0,
"stored_fields": [
"*"
],
"script_fields": {},
"docvalue_fields": [
{
"field": "datetime",
"format": "date_time"
}
],
"_source": {
"excludes": []
},
"query": {
"bool": {
"must": [],
"filter": [
2021-02-22 06:13:30 +00:00
{
"range": {
"datetime": {
2021-09-17 13:50:36 +00:00
"gte": "now-6h",
2021-09-13 05:41:23 +00:00
"lte": "now",
"format": "strict_date_optional_time"
2021-02-22 06:13:30 +00:00
}
}
}
2021-09-13 05:41:23 +00:00
],
"should": [
],
"must_not": []
2021-02-22 06:13:30 +00:00
}
2021-09-13 05:41:23 +00:00
}
}
2021-02-22 06:13:30 +00:00
if "queryStringParameters" in event:
2021-09-13 05:41:23 +00:00
if "vehicles" in event["queryStringParameters"] and event["queryStringParameters"]["vehicles"] != "RS_*;*chase" and event["queryStringParameters"]["vehicles"] != "":
for serial in event["queryStringParameters"]["vehicles"].split(","):
payload["query"]["bool"]["should"].append(
{
"match_phrase": {
"serial.keyword": serial
}
2021-02-22 06:13:30 +00:00
}
2021-09-13 05:41:23 +00:00
)
# for single sonde allow longer predictions
payload['query']['bool']['filter'].pop(0)
2021-04-04 00:47:31 +00:00
logging.debug("Start ES Request")
2021-02-22 06:13:30 +00:00
results = es_request(payload, path, "GET")
2021-04-04 00:47:31 +00:00
logging.debug("Finished ES Request")
2021-02-22 06:13:30 +00:00
output = []
2021-09-13 05:41:23 +00:00
for sonde in results['aggregations']['2']['buckets']:
data = sonde['1']['hits']['hits'][0]['_source']
output.append({
"vehicle": data["serial"],
"time": data['datetime'],
2021-09-14 00:56:26 +00:00
"latitude": data['position'][1],
"longitude": data['position'][0],
2021-09-13 05:41:23 +00:00
"altitude": data['altitude'],
"ascent_rate": data['ascent_rate'],
"descent_rate": data['descent_rate'],
"burst_altitude": data['burst_altitude'],
"descending": 1 if data['descending'] == True else 0,
"landed": 1 if data['landed'] == True else 0,
"data": json.dumps(data['data'])
})
2021-02-22 06:13:30 +00:00
2021-09-17 13:50:36 +00:00
compressed = BytesIO()
with gzip.GzipFile(fileobj=compressed, mode='w') as f:
json_response = json.dumps(output)
f.write(json_response.encode('utf-8'))
gzippedResponse = compressed.getvalue()
return {
"body": base64.b64encode(gzippedResponse).decode(),
"isBase64Encoded": True,
"statusCode": 200,
"headers": {
"Content-Encoding": "gzip",
"content-type": "application/json"
}
}
2021-09-13 05:41:23 +00:00
2021-02-22 06:13:30 +00:00
def es_request(payload, path, method):
# get aws creds
session = boto3.Session()
params = json.dumps(payload)
2021-09-13 05:41:23 +00:00
compressed = BytesIO()
with gzip.GzipFile(fileobj=compressed, mode='w') as f:
f.write(params.encode('utf-8'))
params = compressed.getvalue()
2021-09-13 05:41:23 +00:00
headers = {"Host": HOST, "Content-Type": "application/json",
"Content-Encoding": "gzip"}
2021-02-22 06:13:30 +00:00
request = AWSRequest(
method=method, url=f"https://{HOST}/{path}", data=params, headers=headers
2021-02-22 06:13:30 +00:00
)
2021-09-13 05:41:23 +00:00
SigV4Auth(boto3.Session().get_credentials(),
"es", "us-east-1").add_auth(request)
2021-02-22 06:13:30 +00:00
session = URLLib3Session()
r = session.send(request.prepare())
return json.loads(r.text)
if __name__ == "__main__":
# print(get_sondes({"queryStringParameters":{"lat":"-28.22717","lon":"153.82996","distance":"50000"}}, {}))
# mode: 6hours
2021-09-13 05:41:23 +00:00
# type: positions
# format: json
# max_positions: 0
# position_id: 0
# vehicles: RS_*;*chase
2021-06-18 07:15:39 +00:00
print(predict(
2021-09-13 05:41:23 +00:00
{"queryStringParameters": {
"vehicles": ""
}}, {}
))
2021-02-22 06:13:30 +00:00
# get list of sondes, serial, lat,lon, alt
# and current rate
# for each one, request http://predict.cusf.co.uk/api/v1/?launch_latitude=-37.8136&launch_longitude=144.9631&launch_datetime=2021-02-22T00:15:18.513413Z&launch_altitude=30000&ascent_rate=5&burst_altitude=30000.1&descent_rate=5
# have to set the burst alt slightly higher than the launch