Adding repeater bookmarks and markers, based on RepeaterBook.com.

This commit is contained in:
Marat Fayzullin 2023-08-22 21:35:24 -04:00
parent d7174dea77
commit 187b2a7e6e
6 changed files with 61 additions and 73 deletions

View File

@ -204,5 +204,5 @@ defaultConfig = PropertyLayer(
wsprnet_callsign="N0CALL", wsprnet_callsign="N0CALL",
paging_filter=True, paging_filter=True,
eibi_bookmarks_range=0, eibi_bookmarks_range=0,
repeater_range=100, repeater_range=0,
).readonly() ).readonly()

View File

@ -8,6 +8,7 @@ from owrx.feature import FeatureDetector
from owrx.version import openwebrx_version from owrx.version import openwebrx_version
from owrx.bands import Bandplan from owrx.bands import Bandplan
from owrx.bookmarks import Bookmarks from owrx.bookmarks import Bookmarks
from owrx.repeaters import Repeaters
from owrx.eibi import EIBI from owrx.eibi import EIBI
from owrx.map import Map from owrx.map import Map
from owrx.property import PropertyStack, PropertyDeleted from owrx.property import PropertyStack, PropertyDeleted
@ -215,9 +216,13 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient):
dial_frequencies = Bandplan.getSharedInstance().collectDialFrequencies(frequencyRange) dial_frequencies = Bandplan.getSharedInstance().collectDialFrequencies(frequencyRange)
bookmarks = [b.__dict__() for b in Bookmarks.getSharedInstance().getBookmarks(frequencyRange)] bookmarks = [b.__dict__() for b in Bookmarks.getSharedInstance().getBookmarks(frequencyRange)]
# Search EIBI schedule for bookmarks, if enabled # Search EIBI schedule for bookmarks, if enabled
eibi_range = self.stack["eibi_bookmarks_range"] range = self.stack["eibi_bookmarks_range"]
if eibi_range > 0: if range > 0:
bookmarks += [b.__dict__() for b in EIBI.getSharedInstance().currentBookmarks(frequencyRange, rangeKm=eibi_range)] 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_dial_frequencies(dial_frequencies)
self.write_bookmarks(bookmarks) self.write_bookmarks(bookmarks)

View File

@ -215,11 +215,11 @@ class GeneralSettingsController(SettingsFormController):
), ),
NumberInput( NumberInput(
"repeater_range", "repeater_range",
"Repeater search range", "Repeater bookmarks range",
infotext="Specifies the distance from the receiver location to " infotext="Specifies the distance from the receiver location to "
+ "search RepeaterBook.com for repeaters. Set to 0 to disable " + "search RepeaterBook.com for repeaters when creating automatic "
+ "repeater search.", + "bookmarks. Set to 0 to disable automatic repeater bookmarks.",
validator=RangeValidator(0, 300), validator=RangeValidator(0, 100),
append="km", append="km",
), ),
), ),

View File

@ -225,9 +225,9 @@ class EIBI(object):
# Make sure freq2>freq1 # Make sure freq2>freq1
(f1, f2) = frequencyRange (f1, f2) = frequencyRange
if f1>f2: if f1>f2:
f = f1 f = f1
f1 = f2 f1 = f2
f2 = f f2 = f
# Get entries active at the current time + 1 hour # Get entries active at the current time + 1 hour
now = datetime.utcnow() now = datetime.utcnow()
@ -235,12 +235,14 @@ class EIBI(object):
date = now.year * 10000 + now.month * 100 + now.day date = now.year * 10000 + now.month * 100 + now.day
t1 = now.hour * 100 + now.minute t1 = now.hour * 100 + now.minute
t2 = t1 + hours * 100 t2 = t1 + hours * 100
result = {}
# Get receiver location for computing distance # Get receiver location for computing distance
pm = Config.get() pm = Config.get()
rxPos = (pm["receiver_gps"]["lat"], pm["receiver_gps"]["lon"]) 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)) logger.debug("Creating bookmarks for {0}-{1}kHz within {2}km...".format(f1//1000, f2//1000, rangeKm))
# Search for current entries # Search for current entries
@ -253,7 +255,7 @@ class EIBI(object):
# Check if entry active and within frequency range # Check if entry active and within frequency range
f = entry["freq"] f = entry["freq"]
entryActive = ( 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["date1"] == 0 or entry["date1"] <= date)
and (entry["date2"] == 0 or entry["date2"] >= date) and (entry["date2"] == 0 or entry["date2"] >= date)
) )

View File

@ -4,6 +4,7 @@ from owrx.version import openwebrx_version
from owrx.map import Map, Location from owrx.map import Map, Location
from owrx.aprs import getSymbolData from owrx.aprs import getSymbolData
from owrx.eibi import EIBI from owrx.eibi import EIBI
from owrx.repeaters import Repeaters
from json import JSONEncoder from json import JSONEncoder
from datetime import datetime from datetime import datetime
@ -107,6 +108,7 @@ class Markers(object):
self.markers = {} self.markers = {}
self.rxmarkers = {} self.rxmarkers = {}
self.txmarkers = {} self.txmarkers = {}
self.remarkers = {}
# Load miscellaneous markers from local files # Load miscellaneous markers from local files
for file in self.fileList: for file in self.fileList:
@ -129,11 +131,15 @@ class Markers(object):
# Load current schedule from the EIBI database # Load current schedule from the EIBI database
self.txmarkers = self.loadCurrentTransmitters() self.txmarkers = self.loadCurrentTransmitters()
# Load repeaters from the Repeaters database
self.remarkers = self.loadRepeaters()
# Update map with markers # Update map with markers
logger.debug("Updating map...") logger.debug("Updating map...")
self.updateMap(self.markers) self.updateMap(self.markers)
self.updateMap(self.rxmarkers) self.updateMap(self.rxmarkers)
self.updateMap(self.txmarkers) self.updateMap(self.txmarkers)
self.updateMap(self.remarkers)
# #
# Main Loop # Main Loop
@ -246,8 +252,6 @@ class Markers(object):
cache.update(self.scrapeWebSDR()) cache.update(self.scrapeWebSDR())
logger.debug("Scraping OpenWebRX website...") logger.debug("Scraping OpenWebRX website...")
cache.update(self.scrapeOWRX()) 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 # Save parsed data into a file, if there is anything to save
if cache: if cache:
@ -260,6 +264,29 @@ class Markers(object):
# Following functions scrape data from websites and internal databases # 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): def loadCurrentTransmitters(self):
#url = "https://www.short-wave.info/index.php?txsite=" #url = "https://www.short-wave.info/index.php?txsite="
url = "https://www.google.com/search?q=" url = "https://www.google.com/search?q="
@ -432,58 +459,3 @@ class Markers(object):
# Done # Done
return result 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

View File

@ -646,13 +646,22 @@ class SdrDeviceDescription(object):
NumberInput("initial_squelch_level", "Initial squelch level", append="dBFS"), NumberInput("initial_squelch_level", "Initial squelch level", append="dBFS"),
NumberInput( NumberInput(
"eibi_bookmarks_range", "eibi_bookmarks_range",
"Automatic bookmarks range", "Shortwave bookmarks range",
infotext="Specifies the distance from the receiver location to " infotext="Specifies the distance from the receiver location to "
+ "search EIBI schedules for stations when creating automatic " + "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), validator=RangeValidator(0, 25000),
append="km", 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): def hasAgc(self):
@ -680,7 +689,7 @@ class SdrDeviceDescription(object):
return ["name", "center_freq", "samp_rate", "start_freq", "start_mod", "tuning_step"] return ["name", "center_freq", "samp_rate", "start_freq", "start_mod", "tuning_step"]
def getProfileOptionalKeys(self): 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): def getDeviceSection(self):
return OptionalSection( return OptionalSection(