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 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.