Az EU által üzemeltetett Sentinel-2-es műholdak folyamatosan figyelik Földünk felszínét, több terabyte-nyi adatot előállítva nap mint nap, azonban ha értesítést szeretnénk kapni ha egy általunk megfigyelt területről új műholdkép lesz elérhető, sajnos nem sok szolgáltatás áll rendelkezésünkre. Ebben a bejegyzésben bemutatom, hogy hogyan állítható elő saját e-mail értesítő szolgáltatás Python-ban.

A motiváció

Aki ismeri a Satmapper.hu-t vagy már végigböngészte az oldal tartalmát, az tudja, hogy a Műholdképek menüpont alatt a lehető legfrissebb, 30% alatti felhőzöttségű Sentinel-2 műholdképek érhetőek el két kiválasztott településről. Ezen adatok előállításához először le kell tölteni a vizsgált területről készült műholdképet – aminek lehetőleg felhőmentesnek kell lennie – majd jöhet a szoftveres feldolgozás.

Na de honnan értesül a felhasználó arról, ha új műholdképek érhetőek el egy-egy területről? Némi kutakodás után úgy tűnik, hogy nincs igazán ilyen szolgáltatás, így jobb híján kénytelen voltam ezt a hiányt egy Pythonban írt programmal pótolni.

Követelmények

Mielőtt egyetlen sor kódot is írunk, mindig fontos átgondolni, hogy programunknak milyen általunk támasztott követelményeknek kell megfelelnie. Ebben az esetben ezek a következők:

  • A program egy beolvasott Shapefile alapján keressen új műholdképet
  • Legyen állítható a felhőzöttségi érték, mint keresési paraméter
  • Legyen állítható a keresés időbeli gyakorisága
  • Ha a program talált új műholdképet, küldjön e-mailt az új műholdkép fontosabb adataival
  • Ha a program elküldte az e-mailt adott ideig szüneteltesse a keresést

Előfeltételek

Mielőtt nekikezdünk a kódolásnak szükségünk lesz egy Open Access Hub felhasználói fiókra, mivel a programunk ebben az adatbázisban fog kutatni az új műholdképek után. Az oldalra történő regisztráció ingyenes és körülbelül 24 órán belül aktiválódik.

Az Open Access Hub regisztráción kívül pedig az alábbi Python könyvtárak megléte szükséges:

A fentiek közül a legfontosabb a Sentinelsat, aminek a segítségével tudunk majd csatlakozni az Open Access Hub-ra majd adatokat tudunk kinyerni onnan. Ha ezekkel végeztünk kezdhetjük is a kódolást.

A Python kód

Nyissunk meg egy üres Python fájlt, majd kezdjük el begépelni a következő sorokat.
Az első sorokkal meghívjuk a később szükséges könyvtárakat illetve megadjuk a beolvasni kívánt Shapefile-unk elérési útvonalát. Ebben a példában Budapest shapefile-ját fogom használni.

##########################
# Könyvtárak importálása #
##########################
import os
import geopandas as gpd
from sentinelsat import SentinelAPI, read_geojson, geojson_to_wkt
from datetime import date
from datetime import datetime
import smtplib, ssl
import time
import schedule

#############################
# Shape file elérési útvonal#
#############################
fp_place='shape_file/budapest/budapest.shp'

A következő szakaszban megadjuk az Open Access Hub-hoz szükséges bejelentkezési adatokat, illetve az e-mail küldéshez szükséges címeket. Fontos, hogy ha Gmail fiókot használunk e-mail küldéshez, akkor a beállításoknál engedélyezzük a „Kevésbé biztonságos alkalmazások” hozzáférést, különben a programunk nem tudja a fiókot mailküldésre használni. 

Javasolt az e-mail küldésére egy olyan Gmail fiókot használni amelynél nem bánjuk, hogy ha emiatt a beállítás miatt sebezhetőbbé válik, ezért a maximális biztonság érdekében érdemes egy teljesen új fiókot létrehozni, amit csak erre a feladatra használunk.

########################
# Alapvető paraméterek #
########################
# Open Access Hub bejelentkezési adatok
oah_user='FELHASZNÁLÓNÉV' # Open Access Hub felhasználónév
oah_pass='JELSZÓ' # Open Access Hub jelszó

#E-mail adat
port = 465 # Email port SSL-hez
smtp_server = "smtp.gmail.com" #SMTP szerver
sender_email = "XXXX@gmail.com" # Küldő e-mail címe
receiver_email = "YYYY@gmail.com" # Címzett e-mail címe
password = "MAILPASSWORD" # Küldő e-mail cím jelszava

Ezután adjuk meg a keresési paramétereket majd olvassuk be a korábban megadott Shapefile-t. A keresési paraméterek szabadon változtathatóak, a lehetőségekhez érdemes végigböngészni a Sentinelsat dokumentációját. A max_cloud változónál tudjuk beállítani, hogy csak akkor küldjön értesítést a program ha mondjuk 0-30% közé esik az új műholdkép felhőzöttsége.

########################################################
# Keresési paraméterek - Lásd sentinelsat dokumentáció #
########################################################
start_date='NOW-1DAY'
end_date='NOW'
platformname='Sentinel-2'
processinglevel = 'Level-2A'
min_cloud=0
max_cloud=100

##############################################
# Shapefile megnyitása befoglaló koordináták #
##############################################
shapefile = gpd.read_file(fp_place)
shapefile_EPSG4326=shapefile.to_crs(epsg=4326)
shp_bounds=shapefile_EPSG4326.total_bounds
lonmin=shapefile_EPSG4326.total_bounds[0]
latmin=shapefile_EPSG4326.total_bounds[1]
lonmax=shapefile_EPSG4326.total_bounds[2]
latmax=shapefile_EPSG4326.total_bounds[3]

# WKT előállítása shapefile alapján
wkt = "POINT(%f %f %f %f)" % (float(lonmin) , float(latmin), float(lonmax), float(latmax))

Következő lépésként létrehozzuk azt a függvényt, amit az egész programunk legfontosabb részét fogja végezni. Ez a kódrészlet először felcsatlakozik az Open Access Hub API oldalára majd megnézi, hogy hány darab műholdfelvétel felel meg a keresési kritériumoknak.
Ha ez a szám nagyobb mint nulla, akkor letölti a műholdképhez tartozó adatokat, majd ezeket némi előkészítés után beleírja az értesítő e-mail szövegébe, majd elküldi a korábban megadott e-mail címre. Ha ez megtörtént, 23 órára szünetelteti (sleep) a programot.
Fontos az is, hogy visszajelzést is kapjunk a program futásáról, ezért minden fontosabb művelet után konzol üzenetet íratunk ki.

####################################################
# Függvény új adat kereséséhez és e-mail küldéshez #
####################################################
def job():
    #Sentinel műholdképek keresése SciHub-on, keresési kritériumok alapján
    api = SentinelAPI(oah_user,oah_pass, 'https://scihub.copernicus.eu/apihub')
    count=api.count(area=wkt, date=(start_date, end_date), platformname=platformname,area_relation='Contains',raw=None,cloudcoverpercentage=(min_cloud,max_cloud),limit=20, processinglevel = processinglevel)
    now = datetime.now()
    now = now.strftime("%d/%m/%Y %H:%M:%S")
    print(now+' - Új adat keresése')
    

    if count>0:
        # Elérhető műholdképek adatainak dataframe-be írása
        products = api.query(area=wkt, date=(start_date, end_date), platformname=platformname,area_relation='Contains',raw=None,cloudcoverpercentage=(min_cloud,max_cloud),limit=20, processinglevel = processinglevel)
        products_df = api.to_dataframe(products)
        detail=products_df.iat[0,4]
        
        # E-mailbe írandó adatok formázása
        img_sat=products_df.iloc[0,36] # Műhold név
        img_proc_lvl=products_df.iloc[0,37] # Feldolgozási szint
        img_date=products_df.iloc[0,4][6:16] # Felvétel rögzítésének dátuma
        img_time=products_df.iloc[0,4][17:25] # Felvétel rögzítésének időpontja
        img_cloud=str(products_df.iloc[0,19])[:5]+' %' # Felvétel felhőzöttsége
              
        #E-mail tartalom előkészítése
        subject="Új műholdkép - "+img_date
        body="A vizsgált területről készült új műholdkép adatai.\n\n"+'Műhold: '+img_sat+'\n'+'Feldolgozási szint: '+img_proc_lvl+'\n'+'Felvétel rögzítve: '+img_date+', '+img_time+'\n'+'Felvétel felhőzöttsége: '+img_cloud
        message=f'Subject:{subject}\n\n{body}'      
        
        #E-mail küldése és keresés szüneteltetése
        context = ssl.create_default_context()
        with smtplib.SMTP_SSL(smtp_server, port, context=context) as server:
            server.login(sender_email, password)
            server.sendmail(sender_email, receiver_email, message.encode("utf8"))
        now = datetime.now()
        now = now.strftime("%d/%m/%Y %H:%M:%S")
        print(now+' - E-mail elküldve')
        time.sleep(82800) #23 óra 
        return
    else:
        # Jelezzen ha nincs új műholdkép
        print(now+' - Nem érhető el új műholdkép')
        return

Miután megírtuk a függvényt, nincs más hátra, mint ütemezni annak végrehajtását. Ehhez a schedule parancsot használtam óránkénti futtatást beállítva.

#################################################################
# Függvény futtatása minden órában - Lásd schedule dokumentáció #
#################################################################  
schedule.every().hour.do(job)

while True:
    schedule.run_pending()
    time.sleep(1)

Ezzel majdnem készen is vagyunk, már csak el kell indítani a programot egy olyan számítógépen, amely 0-24 működik és rendelkezik internet csatlakozással. Ehhez én egy viszonlyag olcsó és alacsony áramfogyasztású Raspberry Pi Model B+ -t használok Raspberry Pi operációs rendszerrel. 

 Az elküldött e-mail pedig valahogy így fog kinézni Gmail kliensben:

Remélem hasznos volt a bejegyzés azoknak akik járatosak Python programozásban és egyúttal érdekeltek Sentinel-2 műholdképek feldolgozásában, akiktől pedig távol áll a programozás remélem, hogy nem volt túl rémisztő ez a bejegyzés és esetleg kedvet kaptak ennek a programozási nyelvnek a megismeréséhez.

A fenti kód és a példában szereplő shapefile elérhető GitHub-on akár Jupyter Notebook formában is angol és magyar nyelvű üzenetekkel.

Letöltés GitHub-ról

Megosztás

Ez a weboldal cookie-kat (sütiket) használ, amihez az Ön hozzájárulása szükséges! Részletek

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Bezárás