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",
paging_filter=True,
eibi_bookmarks_range=0,
repeater_range=100,
repeater_range=0,
).readonly()

View File

@ -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)

View File

@ -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",
),
),

View File

@ -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)
)

View File

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

View File

@ -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(