Browse Source

refactor the code to abstract from the weather provider

Sven Czarnian 3 years ago
parent
commit
11e76a3f24
2 changed files with 77 additions and 14 deletions
  1. 16 14
      aman/com/DwdCrawler.py
  2. 61 0
      aman/com/Weather.py

+ 16 - 14
aman/com/DwdCrawler.py

@@ -6,7 +6,6 @@ import urllib.request
 
 from bs4 import BeautifulSoup
 from datetime import datetime as dt
-from threading import Thread
 
 # @brief Checks the DWD pages for wind information
 # Format:
@@ -18,12 +17,10 @@ from threading import Thread
 #               - first element of wind data tuple: minimum altitude AMSL for this wind information
 #               - second element of wind data tuple: wind direction
 #               - third  element of wind data tuple: wind speed (KT)
-class DwdCrawler(Thread):
+class DwdCrawler():
     def __init__(self):
-        Thread.__init__(self)
-        self.dataAvailable = False
-        self.executing = True
-        self.start()
+        self.updateTime = None
+        self.windData = None
 
     def parseGaforAreas(areas : str):
         areas = areas.replace(':', '')
@@ -102,7 +99,7 @@ class DwdCrawler(Thread):
             # analyze the received data
             if None != content:
                 windInformation = []
-                udpdateTime = None
+                nextUpdate = None
                 windTable = []
                 areaIds = None
 
@@ -119,15 +116,18 @@ class DwdCrawler(Thread):
                     elif None != areaIds:
                         windTable = DwdCrawler.parseWindTableRow(line, windTable)
                     elif 'Aktualisierung erfolgt um ' in line:
-                        updateTime = DwdCrawler.parseNextUpdateTime(line)
+                        nextUpdate = DwdCrawler.parseNextUpdateTime(line)
 
                 # return the collected information
-                if 0 != len(windInformation) and None != updateTime:
-                    return updateTime, windInformation
+                if 0 == len(windInformation) or None == nextUpdate:
+                    return None, None
                 else:
-                    return None
+                    return nextUpdate, windInformation
+
+    def receiveWindData(self):
+        self.updateTime = None
+        self.windData = None
 
-    def run(self):
         with urllib.request.urlopen('https://www.dwd.de/DE/fachnutzer/luftfahrt/teaser/luftsportberichte/luftsportberichte_node.html') as site:
             data = site.read().decode('utf-8')
             site.close()
@@ -152,6 +152,8 @@ class DwdCrawler(Thread):
 
             # indicate that new wind data is available
             if None != self.updateTime:
-                self.dataAvailable = True
+                return True
+            else:
+                return False
 
-        self.executing = False
+        return False

+ 61 - 0
aman/com/Weather.py

@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+
+import datetime
+import pytz
+import sys
+import time
+
+from datetime import datetime as dt
+from threading import Thread
+
+from aman.com.DwdCrawler import DwdCrawler
+import aman.config.Weather
+
+class Weather(Thread):
+    def __init__(self, config : aman.config.Weather.Weather):
+        Thread.__init__(self)
+        self.nextUpdate = dt.utcfromtimestamp(int(time.time()))
+        self.lastUpdateTried = None
+        self.stopThread = False
+        self.provider = None
+
+        if 'DWD' == config.Provider.upper():
+            self.provider = DwdCrawler()
+        else:
+            sys.stderr.write('Invalid or unknown weather-provider defined')
+            sys.exit(-1)
+
+        self.start()
+
+    def stop(self):
+        self.stopThread = True
+
+    def currentClock():
+        clock = dt.utcfromtimestamp(int(time.time()))
+        clock = datetime.datetime(
+            year = clock.year,
+            month = clock.month,
+            day = clock.day,
+            hour = clock.hour,
+            minute = clock.minute,
+            second = clock.second,
+            tzinfo = pytz.UTC
+        )
+        return clock
+
+    def run(self):
+        while False == self.stopThread and None != self.provider:
+            now = Weather.currentClock()
+
+            # check if an update is required
+            if None != self.provider.updateTime and self.provider.updateTime > now:
+                time.sleep(1)
+                continue
+
+            # calculate the theoretical next try for an update
+            if None != self.lastUpdateTried:
+                earliestUpdate = self.lastUpdateTried + datetime.timedelta(minutes=2)
+
+            if None == self.lastUpdateTried or self.lastUpdateTried <= now:
+                if True == self.provider.receiveWindData():
+                    self.nextUpdate = self.provider.updateTime