diff --git a/owrx/config/defaults.py b/owrx/config/defaults.py index 423fb615..1c0515f6 100644 --- a/owrx/config/defaults.py +++ b/owrx/config/defaults.py @@ -204,5 +204,5 @@ defaultConfig = PropertyLayer( wsprnet_callsign="N0CALL", paging_filter=True, eibi_bookmarks_range=0, - repeater_range=100, + repeater_range=0, ).readonly() diff --git a/owrx/connection.py b/owrx/connection.py index ae4a5d5c..d058ec1e 100644 --- a/owrx/connection.py +++ b/owrx/connection.py @@ -8,6 +8,7 @@ from owrx.feature import FeatureDetector from owrx.version import openwebrx_version from owrx.bands import Bandplan from owrx.bookmarks import Bookmarks +from owrx.repeaters import Repeaters from owrx.eibi import EIBI from owrx.map import Map from owrx.property import PropertyStack, PropertyDeleted @@ -215,9 +216,13 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient): dial_frequencies = Bandplan.getSharedInstance().collectDialFrequencies(frequencyRange) bookmarks = [b.__dict__() for b in Bookmarks.getSharedInstance().getBookmarks(frequencyRange)] # Search EIBI schedule for bookmarks, if enabled - eibi_range = self.stack["eibi_bookmarks_range"] - if eibi_range > 0: - bookmarks += [b.__dict__() for b in EIBI.getSharedInstance().currentBookmarks(frequencyRange, rangeKm=eibi_range)] + range = self.stack["eibi_bookmarks_range"] + if range > 0: + bookmarks += [b.__dict__() for b in EIBI.getSharedInstance().currentBookmarks(frequencyRange, rangeKm=range)] + # Search RepeaterBook for bookmarks, if enabled + range = self.stack["repeater_range"] + if range > 0: + bookmarks += [b.__dict__() for b in Repeaters.getSharedInstance().getBookmarks(frequencyRange, rangeKm=range)] self.write_dial_frequencies(dial_frequencies) self.write_bookmarks(bookmarks) diff --git a/owrx/controllers/settings/general.py b/owrx/controllers/settings/general.py index 349bda2b..4be68256 100644 --- a/owrx/controllers/settings/general.py +++ b/owrx/controllers/settings/general.py @@ -215,11 +215,11 @@ class GeneralSettingsController(SettingsFormController): ), NumberInput( "repeater_range", - "Repeater search range", + "Repeater bookmarks range", infotext="Specifies the distance from the receiver location to " - + "search RepeaterBook.com for repeaters. Set to 0 to disable " - + "repeater search.", - validator=RangeValidator(0, 300), + + "search RepeaterBook.com for repeaters when creating automatic " + + "bookmarks. Set to 0 to disable automatic repeater bookmarks.", + validator=RangeValidator(0, 100), append="km", ), ), diff --git a/owrx/eibi.py b/owrx/eibi.py index e765ea2c..7c1b24e3 100644 --- a/owrx/eibi.py +++ b/owrx/eibi.py @@ -225,9 +225,9 @@ class EIBI(object): # Make sure freq2>freq1 (f1, f2) = frequencyRange if f1>f2: - f = f1 - f1 = f2 - f2 = f + f = f1 + f1 = f2 + f2 = f # Get entries active at the current time + 1 hour now = datetime.utcnow() @@ -235,12 +235,14 @@ class EIBI(object): date = now.year * 10000 + now.month * 100 + now.day t1 = now.hour * 100 + now.minute t2 = t1 + hours * 100 - result = {} # Get receiver location for computing distance pm = Config.get() rxPos = (pm["receiver_gps"]["lat"], pm["receiver_gps"]["lon"]) + # No result yet + result = {} + logger.debug("Creating bookmarks for {0}-{1}kHz within {2}km...".format(f1//1000, f2//1000, rangeKm)) # Search for current entries @@ -253,7 +255,7 @@ class EIBI(object): # Check if entry active and within frequency range f = entry["freq"] entryActive = ( - f >= f1 and f <= f2 and entry["days"][day] != "." + f1 <= f <= f2 and entry["days"][day] != "." and (entry["date1"] == 0 or entry["date1"] <= date) and (entry["date2"] == 0 or entry["date2"] >= date) ) diff --git a/owrx/markers.py b/owrx/markers.py index 15f4ebac..a328ad93 100644 --- a/owrx/markers.py +++ b/owrx/markers.py @@ -4,6 +4,7 @@ from owrx.version import openwebrx_version from owrx.map import Map, Location from owrx.aprs import getSymbolData from owrx.eibi import EIBI +from owrx.repeaters import Repeaters from json import JSONEncoder from datetime import datetime @@ -107,6 +108,7 @@ class Markers(object): self.markers = {} self.rxmarkers = {} self.txmarkers = {} + self.remarkers = {} # Load miscellaneous markers from local files for file in self.fileList: @@ -129,11 +131,15 @@ class Markers(object): # Load current schedule from the EIBI database self.txmarkers = self.loadCurrentTransmitters() + # Load repeaters from the Repeaters database + self.remarkers = self.loadRepeaters() + # Update map with markers logger.debug("Updating map...") self.updateMap(self.markers) self.updateMap(self.rxmarkers) self.updateMap(self.txmarkers) + self.updateMap(self.remarkers) # # Main Loop @@ -246,8 +252,6 @@ class Markers(object): cache.update(self.scrapeWebSDR()) logger.debug("Scraping OpenWebRX website...") cache.update(self.scrapeOWRX()) - logger.debug("Scraping RepeaterBook website...") - cache.update(self.scrapeRepeaterBook()) # Save parsed data into a file, if there is anything to save if cache: @@ -260,6 +264,29 @@ class Markers(object): # Following functions scrape data from websites and internal databases # + def loadRepeaters(self, rangeKm: int = 100): + # No result yet + result = {} + # Refresh / load repeaters database, as needed + Repeaters.getSharedInstance().refresh() + # Load repeater sites from repeaters database + for entry in Repeaters.getSharedInstance().getAllInRange(rangeKm): + rl = MarkerLocation({ + "type" : "feature", + "mode" : "Repeaters", + "id" : entry["name"], + "lat" : entry["lat"], + "lon" : entry["lon"], + "freq" : entry["freq"], + "mmode" : entry["mode"], + "status" : entry["status"], + "updated" : entry["updated"], + "comment" : entry["comment"] + }) + result[rl.getId()] = rl + # Done + return result + def loadCurrentTransmitters(self): #url = "https://www.short-wave.info/index.php?txsite=" url = "https://www.google.com/search?q=" @@ -432,58 +459,3 @@ class Markers(object): # Done return result - def scrapeRepeaterBook(self, url: str = "https://www.repeaterbook.com/api/export.php?qtype=prox&dunit=km&lat={lat}&lng={lon}&dist={range}"): - result = {} - try: - pm = Config.get() - lat = pm["receiver_gps"]["lat"] - lon = pm["receiver_gps"]["lon"] - dist = pm["repeater_range"] - url = url.format(lat = lat, lon = lon, range = dist) - hdrs = { "User-Agent": "OpenWebRX+/" + openwebrx_version } - req = urllib.request.Request(url, headers = hdrs) - data = urllib.request.urlopen(req).read().decode("utf-8") - data = json.loads(data) - # Ignore empty or invalid responses - if "results" not in data: - return result - # For every entry in the response... - for entry in data["results"]: - # Get location - lat = float(entry["Lat"]) - lon = float(entry["Long"]) - # Guess main operating mode, prefer free modes - if "FM Analog" in entry and entry["FM Analog"]=="Yes": - mmode = "fm" - elif "M17" in entry and entry["M17"]=="Yes": - mmode = "m17" - elif "DMR" in entry and entry["DMR"]=="Yes": - mmode = "dmr" - elif "D-Star" in entry and entry["D-Star"]=="Yes": - mmode = "dstar" - elif "System Fusion" in entry and entry["System Fusion"]=="Yes": - mmode = "ysf" - elif "NXDN" in entry and entry["NXDN"]=="Yes": - mmode = "nxdn" - else: - mmode = "fm" - # Create marker - rl = MarkerLocation({ - "type" : "feature", - "mode" : "Repeaters", - "id" : entry["Callsign"], - "lat" : lat, - "lon" : lon, - "freq" : int(float(entry["Frequency"]) * 1000000), - "mmode" : mmode, - "status" : entry["Operational Status"], - "updated" : entry["Last Update"], - "comment" : entry["Notes"] - }) - result[rl.getId()] = rl - - except Exception as e: - logger.debug("scrapeRepeaterBook() exception: {0}".format(e)) - - # Done - return result diff --git a/owrx/source/__init__.py b/owrx/source/__init__.py index fd2c9efc..e02ca213 100644 --- a/owrx/source/__init__.py +++ b/owrx/source/__init__.py @@ -646,13 +646,22 @@ class SdrDeviceDescription(object): NumberInput("initial_squelch_level", "Initial squelch level", append="dBFS"), NumberInput( "eibi_bookmarks_range", - "Automatic bookmarks range", + "Shortwave bookmarks range", infotext="Specifies the distance from the receiver location to " + "search EIBI schedules for stations when creating automatic " - + "bookmarks. Set to 0 to disable automatic bookmarks.", + + "bookmarks. Set to 0 to disable automatic EIBI bookmarks.", validator=RangeValidator(0, 25000), append="km", ), + NumberInput( + "repeater_range", + "Repeater bookmarks range", + infotext="Specifies the distance from the receiver location to " + + "search RepeaterBook.com for repeaters when creating automatic " + + "bookmarks. Set to 0 to disable automatic repeater bookmarks.", + validator=RangeValidator(0, 100), + append="km", + ), ] def hasAgc(self): @@ -680,7 +689,7 @@ class SdrDeviceDescription(object): return ["name", "center_freq", "samp_rate", "start_freq", "start_mod", "tuning_step"] def getProfileOptionalKeys(self): - return ["initial_squelch_level", "rf_gain", "lfo_offset", "waterfall_levels", "eibi_bookmarks_range"] + return ["initial_squelch_level", "rf_gain", "lfo_offset", "waterfall_levels", "eibi_bookmarks_range", "repeater_range"] def getDeviceSection(self): return OptionalSection(