Where is the ISS

import requests
from maplibre import (
    Layer,
    LayerType,
    Map,
    MapContext,
    MapOptions,
    output_maplibregl,
    render_maplibregl,
)
from maplibre.sources import GeoJSONSource
from shiny import App, reactive, ui

MAX_FEATURES = 30
SOURCE_ID_ISS_POSITION = "iss_position"
SOURCE_ID_ISS_LAST_POSITIONS = "iss-last-positions"


def where_is_the_iss() -> tuple:
    r = requests.get("https://api.wheretheiss.at/v1/satellites/25544").json()
    return (r["longitude"], r["latitude"])


def create_feature(lng_lat: tuple) -> dict:
    return {
        "type": "Feature",
        "geometry": {
            "type": "Point",
            "coordinates": lng_lat,
        },
        "properties": {"coords": ", ".join(map(str, lng_lat))},
    }


lng_lat = where_is_the_iss()
feature = create_feature(where_is_the_iss())
feature_collection = {"type": "FeatureCollection", "features": [feature]}

app_ui = ui.page_fluid(
    ui.panel_title("Where is the ISS"),
    ui.div("Click on Update to get the current position of the ISS."),
    ui.div(
        "The yellow dots show the positions before. Hover the blue dot to display the coordinates."
    ),
    output_maplibregl("mapylibre", height=600),
    ui.input_action_button("update", "Update"),
)


def server(input, output, session):
    @render_maplibregl
    def mapylibre():
        m = Map(MapOptions(center=lng_lat, zoom=3))
        m.set_paint_property("water", "fill-color", "darkblue")
        m.add_source(
            SOURCE_ID_ISS_LAST_POSITIONS, GeoJSONSource(data=feature_collection)
        )
        m.add_layer(
            Layer(
                type=LayerType.CIRCLE,
                source=SOURCE_ID_ISS_LAST_POSITIONS,
                paint={"circle-color": "yellow", "circle-radius": 5},
            ),
        )
        m.add_source(SOURCE_ID_ISS_POSITION, GeoJSONSource(data=feature))
        m.add_layer(
            Layer(
                type=LayerType.CIRCLE,
                id="iss-position",
                source=SOURCE_ID_ISS_POSITION,
                paint={"circle-color": "lightblue", "circle-radius": 7},
            )
        )
        m.add_tooltip("iss-position", "coords")
        return m

    @reactive.Effect
    @reactive.event(input.update)
    async def update():
        print("Fetching new position")
        lng_lat = where_is_the_iss()
        print(lng_lat)
        if len(feature_collection["features"]) == MAX_FEATURES:
            feature_collection["features"] = []

        async with MapContext("mapylibre") as m:
            feature = create_feature(lng_lat)
            m.set_data(SOURCE_ID_ISS_POSITION, feature)
            feature_collection["features"].append(feature)
            m.set_data(SOURCE_ID_ISS_LAST_POSITIONS, feature_collection)
            m.add_call("flyTo", {"center": lng_lat, "speed": 0.5})


app = App(app_ui, server)

Run example:

poetry run uvicorn docs.examples.where_is_the_iss.app:app --reload