Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- import sys
- import math
- import json
- from time import sleep, time
- import urllib2
- from pprint import pprint, pformat
- import traceback
- import datetime
- import smtplib
- ### USER SETTINGS
- # GPS location
- USER_LAT = 52.0
- USER_LON = 21.0
- USER_ALT = 100
- # minimal distance - kilometers
- USER_DIST = 700
- # days between re-notification for particular payload
- USER_CACHE_DAYS = 2
- # email notification
- USER_EMAIL_ONOFF = 1
- USER_EMAIL_FROMADDR = "yourname@gmail.com"
- USER_EMAIL_USERNAME = 'yourname'
- USER_EMAIL_TOADDR = 'yourname@gmail.com'
- USER_EMAIL_PWD = 'yourpassword'
- # smsapi.pl notification - https://github.com/smsapi/smsapi-python-client
- USER_SMS_ONOFF = 1
- USER_SMS_USERNAME = 'yourname@gmail.com'
- USER_SMS_PWD = 'yourpassword'
- USER_SMS_RECIPENT = '601123456'
- # slack notification
- USER_SLACK_ONOFF = 1
- USER_SLACK_TOKEN = '..........'
- ### end USER SETTINGS
- TIME_FORMAT = '%Y-%m-%d %H:%M:%S'
- DATA_FILE = sys.argv[0] + '.reports'
- ################################################################################
- ################################################################################
- ################################################################################
- def google_elevation(lat, lon):
- elevation_json = urllib2.urlopen('http://maps.googleapis.com/maps/api/elevation/json?locations=' + str(lat) + ',' + str(lon) + '&sensor=true')
- return round(json.load(elevation_json)['results'][0]['elevation'])
- def getMyPos():
- return USER_LAT, USER_LON, USER_ALT
- def calcDistanceBearingElevation(lat1, lon1, alt1, lat2, lon2, alt2):
- '''
- based on:
- https://github.com/jamescoxon/dl-fldigi/blob/master/src/dl_fldigi/location.cxx
- '''
- def deg2rad(i_deg):
- return i_deg/180.0*math.pi
- def rad2deg(i_rad):
- return i_rad*180/math.pi
- radius = 6371; # km
- lat1 = deg2rad(lat1);
- lon1 = deg2rad(lon1);
- lat2 = deg2rad(lat2);
- lon2 = deg2rad(lon2);
- d_lon = lon2 - lon1;
- sa = math.cos(lat2) * math.sin(d_lon);
- sb = (math.cos(lat1) * math.sin(lat2)) - (math.sin(lat1) * math.cos(lat2) * math.cos(d_lon));
- bearing = math.atan2(sa, sb);
- bearing = rad2deg(bearing);
- if (bearing < 0):
- bearing += 360;
- bearing = round(bearing);
- aa = math.sqrt((sa * sa) + (sb * sb));
- ab = (math.sin(lat1) * math.sin(lat2)) + (math.cos(lat1) * math.cos(lat2) * math.cos(d_lon));
- angle_at_centre = math.atan2(aa, ab);
- great_circle_distance = angle_at_centre * radius;
- # great_circle_distance = great_circle_distance.toFixed(2);
- ta = radius + alt1 * 0.001; # m to km
- tb = radius + alt2 * 0.001; # m to km
- ea = (math.cos(angle_at_centre) * tb) - ta;
- eb = math.sin(angle_at_centre) * tb;
- elevation = math.atan2(ea, eb);
- elevation = rad2deg(elevation);
- # elevation = elevation.toFixed(1);
- distance = math.sqrt((ta * ta) + (tb * tb) - 2 * tb * ta * math.cos(angle_at_centre));
- # distance = distance.toFixed(2);
- result = {
- "distance" : round(distance, 1),
- "great_circle_distance" : round(great_circle_distance, 1),
- "bearing" : bearing,
- "elevation" : round(elevation, 2)
- }
- return result
- ################################################################################
- ################################################################################
- ################################################################################
- def getFlights():
- flights_json = urllib2.urlopen('http://habitat.habhub.org/habitat/_design/flight/_view/end_start_including_payloads?startkey=[' + str(int(time())) + ']&include_docs=True')
- flights = json.load(flights_json)['rows']
- res = [ f for f in flights if f['doc']['type'] == 'flight' ]
- return res
- def getTelemetry(i_payloadName, max_positions=1 ):
- data_url = "http://spacenear.us/tracker/datanew.php";
- data_str = "mode=position&type=positions&format=json&max_positions=" + str(max_positions) + "&position_id=0&vehicles=" + urllib2.quote(i_payloadName);
- _url = data_url + '?' + data_str
- res = urllib2.urlopen(_url)
- res = json.load(res)
- return res['positions']['position']
- def getPayloads(i_flights):
- all_docs = urllib2.urlopen('http://habitat.habhub.org/habitat/_design/flight/_view/end_start_including_payloads?startkey=[' + str(int(time())) + ']&include_docs=True')
- all_docs = json.load(all_docs)['rows']
- flyingPayloadsIds = []
- for f in i_flights:
- flyingPayloadsIds.extend( f['doc']['payloads'] )
- res = []
- for f in all_docs:
- if f['doc']['type'] == 'payload_configuration' and f['doc']['_id'] in flyingPayloadsIds:
- f['telemetry'] = getTelemetry(f['doc']['name'],1)
- res.append(f)
- return res
- def getNearPayloads(i_dist=700, i_pos=None, i_payloads=None):
- '''
- i_dist - minimal distance for a payload to be considered
- i_pos - USER location tuple (lat,lon,alt)
- '''
- if not i_pos:
- i_pos = getMyPos()
- if not i_payloads:
- i_payloads = getPayloads(getFlights())
- res = []
- for payload in i_payloads:
- telemetry = payload['telemetry'][0]
- d = calcDistanceBearingElevation(
- i_pos[0], i_pos[1], i_pos[2],
- float(telemetry['gps_lat']), float(telemetry['gps_lon']), float(telemetry['gps_alt'])
- )
- if d['distance'] < i_dist:
- #add distance to payload
- payload['distance'] = d
- res.append(payload)
- return res
- ################################################################################
- ################################################################################
- ################################################################################
- def deleteOldEntries(i_fname = None):
- '''
- remove old entries from cache
- '''
- if not i_fname:
- i_fname = DATA_FILE
- data = json.loads( open(DATA_FILE).read() )
- keys_to_remove = []
- for p in data:
- p_time = datetime.datetime.strptime(data[p]['time'], TIME_FORMAT)
- delta_time = datetime.datetime.utcnow() - p_time
- if delta_time.days > USER_CACHE_DAYS:
- keys_to_remove.append(p)
- for ktr in keys_to_remove:
- del data[ktr]
- open(DATA_FILE, 'w').write( json.dumps(data,indent=4,sort_keys=True) )
- def getReportTimes():
- try: data = json.loads( open(DATA_FILE).read() )
- except: data = {}
- return data
- def lastReportTime(i_payload):
- try:
- all_reports = getReportTimes()
- payload_name = i_payload['doc']['name']
- if payload_name in all_reports:
- lrt = all_reports[payload_name]['time']
- lrt = datetime.datetime.strptime(lrt, TIME_FORMAT)
- return lrt
- except:
- print traceback.format_exc()
- return None
- ################################################################################
- ################################################################################
- ################################################################################
- def niceTelemetry(i_payload):
- msg_data = {}
- msg_data['name'] = i_payload['doc']['name']
- msg_data['dis'] = i_payload['distance']
- msg_data['lat'] = i_payload['telemetry'][0]['gps_lat']
- msg_data['lon'] = i_payload['telemetry'][0]['gps_lon']
- msg_data['alt'] = i_payload['telemetry'][0]['gps_alt']
- return pformat(msg_data)
- def send_mail(subj, message):
- msg = "\r\n".join([
- "From: %s" % USER_EMAIL_USERNAME,
- "To: %s" % USER_EMAIL_TOADDR,
- "Subject: %s" % subj,
- "",
- message
- ])
- server = smtplib.SMTP('smtp.gmail.com:587')
- server.starttls()
- server.login(USER_EMAIL_USERNAME,USER_EMAIL_PWD)
- server.sendmail(USER_EMAIL_FROMADDR, USER_EMAIL_TOADDR, msg)
- server.quit()
- def notify_email(i_payload):
- if not USER_EMAIL_ONOFF:
- return
- subj = 'hab_alert: ' + i_payload['doc']['name']
- message = niceTelemetry(i_payload)
- send_mail(subj, message)
- def notify_sms(i_payload):
- if not USER_SMS_ONOFF:
- return
- try:
- from smsapi.client import SmsAPI
- except ImportError:
- return
- api = SmsAPI()
- api.set_username(USER_SMS_USERNAME)
- api.set_password(USER_SMS_PWD)
- api.service('sms').action('send')
- msg = 'hab_alert: ' + niceTelemetry(i_payload)
- api.set_content(msg)
- api.set_to(USER_SMS_RECIPENT)
- result = api.execute()
- #for r in result: print(r.id, r.points, r.status)
- def notifySlack(i_payload,slack_channel="#info"):
- if not USER_SLACK_ONOFF:
- return
- try:
- from slackclient import SlackClient
- except ImportError:
- return
- subj = 'hab_alert: ' + i_payload['doc']['name']
- message = niceTelemetry(i_payload)
- try:
- sc = SlackClient(USER_SLACK_TOKEN)
- try:
- sc.api_call("chat.postMessage", channel=slack_channel, text=message, username='wintermute')
- except:
- print "Unable to send slack notification!"
- except:
- print "notifyUser failed"
- print traceback.format_exc()
- ################################################################################
- ################################################################################
- ################################################################################
- def reportPayload(i_payload):
- all_reports = getReportTimes()
- p_name = i_payload['doc']['name']
- # already notified
- if p_name in all_reports:
- return
- #
- notify_email(i_payload)
- notify_sms(i_payload)
- notifySlack(i_payload)
- # save to reports file
- all_reports = getReportTimes()
- all_reports[p_name] = {}
- all_reports[p_name]['time'] = datetime.datetime.utcnow().strftime(TIME_FORMAT)
- all_reports[p_name]['distance'] = i_payload['distance']
- all_reports[p_name]['gps_lat'] = i_payload['telemetry'][0]['gps_lat']
- all_reports[p_name]['gps_lon'] = i_payload['telemetry'][0]['gps_lon']
- all_reports[p_name]['gps_alt'] = i_payload['telemetry'][0]['gps_alt']
- try:
- json_data = json.dumps(all_reports, indent=4,sort_keys=True)
- open(DATA_FILE, 'w').write(json_data)
- except:
- print traceback.format_exc()
- print "Error writing ", DATA_FILE
- ################################################################################
- ################################################################################
- ################################################################################
- def main():
- try:
- deleteOldEntries()
- except:
- print traceback.format_exc()
- print "Error deleting old entries"
- try:
- payloads = getNearPayloads(i_dist=USER_DIST)
- except:
- print traceback.format_exc()
- print "Error getting near payloads"
- return
- for p in payloads:
- reportPayload(p)
- if __name__ == '__main__':
- main()
- '''
- {'distance': {'bearing': 244.0,
- 'distance': 536.3,
- 'elevation': -1.82,
- 'great_circle_distance': 536.2},
- u'doc': {u'_id': u'120d309024cfd89edfcd528fa7873013',
- u'_rev': u'1-a90f121c3cbd6b796be3b4b7dc466b83',
- u'metadata': {u'description': u'0001'},
- u'name': u'SP3OSJ',
- u'sentences': [{u'callsign': u'SP3OSJ',
- u'checksum': u'crc16-ccitt',
- u'description': u'SP3OSJ Long flight',
- u'fields': [{u'name': u'sentence_id',
- u'sensor': u'base.ascii_int'},
- {u'name': u'time',
- u'sensor': u'stdtelem.time'},
- {u'format': u'dd.dddd',
- u'name': u'latitude',
- u'sensor': u'stdtelem.coordinate'},
- {u'format': u'dd.dddd',
- u'name': u'longitude',
- u'sensor': u'stdtelem.coordinate'},
- {u'name': u'altitude',
- u'sensor': u'base.ascii_int'},
- {u'name': u'temperature_internal',
- u'sensor': u'base.ascii_int'},
- {u'name': u'satellites',
- u'sensor': u'base.ascii_int'},
- {u'name': u'km',
- u'sensor': u'base.ascii_float'},
- {u'name': u'battery',
- u'sensor': u'base.ascii_float'},
- {u'name': u'solar',
- u'sensor': u'base.ascii_float'}],
- u'protocol': u'UKHAS'}],
- u'time_created': u'2013-09-26T21:34:32+02:00',
- u'transmissions': [{u'baud': 100,
- u'description': u'SP3OSJ_100bd',
- u'encoding': u'ASCII-7',
- u'frequency': 437700000,
- u'mode': u'USB',
- u'modulation': u'RTTY',
- u'parity': u'none',
- u'shift': 470,
- u'stop': 2}],
- u'type': u'payload_configuration'},
- u'id': u'1da797e765edc82a75f0093b479bcff8',
- u'key': [1484265599, 1483660800, u'1da797e765edc82a75f0093b479bcff8', 1],
- u'value': {u'_id': u'120d309024cfd89edfcd528fa7873013'}}
- '''
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement