satnogs-demo-display/update.py

147 lines
4.3 KiB
Python

#!/bin/env python3
import os
import requests
import pytz
from datetime import datetime, timedelta
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
from io import BytesIO
from geopy.geocoders import Nominatim
FONT_SIZE = 40
FONT_SIZE_SMALL = 20
TEXT_COLOR = (255, 255, 255, 255)
def invert_back_white(img):
pixels = img.load()
for y in range(img.size[1]):
for x in range(img.size[0]):
r, g, b, _ = pixels[x, y]
if abs(r - g) < 5 and abs(r - g) < 5 and abs(b - g) < 5:
pixels[x, y] = (255 - r, 255 - g, 255 - b, 255)
def scale_to_height(img, new_height):
width, height = img.size
new_width = int(new_height * width / height)
return img.resize((new_width, new_height))
def scale_to_width(img, new_width):
width, height = img.size
new_height = int(new_width * height / width)
return img.resize((new_width, new_height))
def main():
now = datetime.now(pytz.utc)
earlier = now - timedelta(hours=1)
params = {
'start': earlier.isoformat(),
'end': now.isoformat(),
'status': 'good',
}
resp = requests.get('https://network.satnogs.org/api/observations',
params=params)
obs = resp.json()
obs = reversed(sorted(obs, key=lambda x: x['end']))
for ob in obs:
if ob['waterfall'] is not None:
break
if ob['waterfall'] is None:
print("No observations with waterfall found")
return
resp = requests.get('https://db.satnogs.org/api/satellites/%s/' %
ob['norad_cat_id'])
sat_name = resp.json()['name']
sat_img_url = None
if 'image' in resp.json().keys():
sat_img_url = "https://db-satnogs.freetls.fastly.net/media/%s" % (
resp.json()['image'])
geolocator = Nominatim(
user_agent=
"satnogs-demo-display - https://forgejo.zenerdio.de/sebastian/satnogs-demo-display"
)
mode_desc = ob['transmitter_mode']
frequency = ob['observation_frequency'] / 1_000_000
coord = "%f, %f" % (ob['station_lat'], ob['station_lng'])
address = geolocator.reverse(coord, exactly_one=True,
language="en").raw['address']
city = address.get('city', '')
country = address.get('country', '')
station_location = ""
if city != "":
station_location += "near " + city + " "
if country != "":
station_location += "in " + country
resp = requests.get(ob['waterfall'])
waterfall = Image.open(BytesIO(resp.content)).convert('RGBA')
invert_back_white(waterfall)
waterfall = scale_to_height(waterfall, 1024)
water_width, _ = waterfall.size
logo = Image.open("satnogs-logo.png").convert('RGBA')
logo_w, logo_h = logo.size
invert_back_white(logo)
sat_img = None
if sat_img_url is not None:
resp = requests.get(sat_img_url)
sat_img_aplha = Image.open(BytesIO(resp.content)).convert('RGBA')
alpha_chan = sat_img_aplha.convert('RGBA').split()[-1]
sat_img = Image.new("RGBA", sat_img_aplha.size, (255, 255, 255, 255))
sat_img.paste(sat_img_aplha, mask=alpha_chan)
sat_img_width, sat_img_height = sat_img.size
if sat_img_width > sat_img_height:
sat_img = scale_to_width(sat_img, 500)
else:
sat_img = scale_to_height(sat_img, 500)
img = Image.new('RGBA', (1280, 1024))
draw = ImageDraw.Draw(img)
draw.rectangle((0, 0, 1280, 1024), fill=(0, 0, 0, 255))
station_name = ob['station_name']
if len(station_name) > 20:
station_name = station_name[:20] + "..."
infos = "Satellite: %s\nStation: %s\n%s\nMode: %s\nFrequency: %f MHz\nStart: %s\nEnd: %s" % (
sat_name, station_name, station_location, mode_desc, frequency,
ob['start'], ob['end'])
font = ImageFont.truetype("Montserrat-Regular.otf", FONT_SIZE)
draw.text((water_width + 100, logo_h + 50), infos, TEXT_COLOR, font=font)
img.paste(waterfall, (0, 0))
img.paste(logo, (water_width + 100, 20))
if sat_img != None:
img.paste(sat_img, (water_width + 100, 480))
font = ImageFont.truetype("Montserrat-Regular.otf", FONT_SIZE_SMALL)
draw.text((950, 1000), "Geocoding by Nominatim/OSM", TEXT_COLOR, font=font)
img.save('waterfall_tmp.png')
os.rename('waterfall_tmp.png', 'waterfall.png')
if __name__ == '__main__':
main()