Merge branch 'develop' into packet
This commit is contained in:
@ -1,10 +1,12 @@
|
||||
import threading
|
||||
import socket
|
||||
from owrx.source import SdrService
|
||||
from owrx.bands import Bandplan
|
||||
from csdr import dsp, output
|
||||
from owrx.wsjt import WsjtParser
|
||||
from owrx.aprs import AprsParser
|
||||
from owrx.config import PropertyManager
|
||||
from owrx.source import Resampler
|
||||
|
||||
import logging
|
||||
|
||||
@ -81,19 +83,101 @@ class ServiceHandler(object):
|
||||
self.startupTimer = threading.Timer(10, self.updateServices)
|
||||
self.startupTimer.start()
|
||||
|
||||
def getAvailablePort(self):
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.bind(("", 0))
|
||||
s.listen(1)
|
||||
port = s.getsockname()[1]
|
||||
s.close()
|
||||
return port
|
||||
|
||||
def updateServices(self):
|
||||
logger.debug("re-scheduling services due to sdr changes")
|
||||
self.stopServices()
|
||||
cf = self.source.getProps()["center_freq"]
|
||||
srh = self.source.getProps()["samp_rate"] / 2
|
||||
sr = self.source.getProps()["samp_rate"]
|
||||
srh = sr / 2
|
||||
frequency_range = (cf - srh, cf + srh)
|
||||
self.services = [
|
||||
self.setupService(dial["mode"], dial["frequency"])
|
||||
|
||||
dials = [
|
||||
dial
|
||||
for dial in Bandplan.getSharedInstance().collectDialFrequencies(frequency_range)
|
||||
if self.isSupported(dial["mode"])
|
||||
]
|
||||
|
||||
def setupService(self, mode, frequency):
|
||||
if not dials:
|
||||
logger.debug("no services available")
|
||||
return
|
||||
|
||||
self.services = []
|
||||
|
||||
for group in self.optimizeResampling(dials, sr):
|
||||
frequencies = sorted([f["frequency"] for f in group])
|
||||
min = frequencies[0]
|
||||
max = frequencies[-1]
|
||||
cf = (min + max) / 2
|
||||
bw = max - min
|
||||
logger.debug("group center frequency: {0}, bandwidth: {1}".format(cf, bw))
|
||||
resampler_props = PropertyManager()
|
||||
resampler_props["center_freq"] = cf
|
||||
# TODO the + 24000 is a temporary fix since the resampling optimizer does not account for required bandwidths
|
||||
resampler_props["samp_rate"] = bw + 24000
|
||||
resampler = Resampler(resampler_props, self.getAvailablePort(), self.source)
|
||||
resampler.start()
|
||||
self.services.append(resampler)
|
||||
|
||||
for dial in group:
|
||||
self.services.append(self.setupService(dial["mode"], dial["frequency"], resampler))
|
||||
|
||||
def optimizeResampling(self, freqs, bandwidth):
|
||||
freqs = sorted(freqs, key=lambda f: f["frequency"])
|
||||
distances = [{
|
||||
"frequency": freqs[i]["frequency"],
|
||||
"distance": freqs[i+1]["frequency"] - freqs[i]["frequency"],
|
||||
} for i in range(0, len(freqs)-1)]
|
||||
|
||||
distances = [d for d in distances if d["distance"] > 0]
|
||||
|
||||
distances = sorted(distances, key=lambda f: f["distance"], reverse=True)
|
||||
|
||||
|
||||
def calculate_usage(num_splits):
|
||||
splits = sorted([f["frequency"] for f in distances[0:num_splits]])
|
||||
previous = 0
|
||||
groups = []
|
||||
for split in splits:
|
||||
groups.append([f for f in freqs if previous < f["frequency"] <= split])
|
||||
previous = split
|
||||
groups.append([f for f in freqs if previous < f["frequency"]])
|
||||
|
||||
def get_bandwitdh(group):
|
||||
freqs = sorted([f["frequency"] for f in group])
|
||||
# the group will process the full BW once, plus the reduced BW once for each group member
|
||||
return bandwidth + len(group) * (freqs[-1] - freqs[0] + 24000)
|
||||
|
||||
total_bandwidth = sum([get_bandwitdh(group) for group in groups])
|
||||
return {
|
||||
"num_splits": num_splits,
|
||||
"total_bandwidth": total_bandwidth,
|
||||
"groups": groups,
|
||||
}
|
||||
|
||||
|
||||
usages = [calculate_usage(i) for i in range(0, len(freqs))]
|
||||
# this is simulating no resampling. i haven't seen this as the best result yet
|
||||
usages += [{
|
||||
"num_splits": None,
|
||||
"total_bandwidth": bandwidth * len(freqs),
|
||||
"groups": [freqs]
|
||||
}]
|
||||
results = sorted(usages, key=lambda f: f["total_bandwidth"])
|
||||
|
||||
for r in results:
|
||||
logger.debug("splits: {0}, total: {1}".format(r["num_splits"], r["total_bandwidth"]))
|
||||
|
||||
return results[0]["groups"]
|
||||
|
||||
def setupService(self, mode, frequency, source):
|
||||
logger.debug("setting up service {0} on frequency {1}".format(mode, frequency))
|
||||
# TODO selecting outputs will need some more intelligence here
|
||||
if mode == "packet":
|
||||
@ -101,8 +185,8 @@ class ServiceHandler(object):
|
||||
else:
|
||||
output = WsjtServiceOutput(frequency)
|
||||
d = dsp(output)
|
||||
d.nc_port = self.source.getPort()
|
||||
d.set_offset_freq(frequency - self.source.getProps()["center_freq"])
|
||||
d.nc_port = source.getPort()
|
||||
d.set_offset_freq(frequency - source.getProps()["center_freq"])
|
||||
if mode == "packet":
|
||||
d.set_demodulator("nfm")
|
||||
d.set_bpf(-4000, 4000)
|
||||
@ -111,7 +195,7 @@ class ServiceHandler(object):
|
||||
d.set_bpf(0, 3000)
|
||||
d.set_secondary_demodulator(mode)
|
||||
d.set_audio_compression("none")
|
||||
d.set_samp_rate(self.source.getProps()["samp_rate"])
|
||||
d.set_samp_rate(source.getProps()["samp_rate"])
|
||||
d.start()
|
||||
return d
|
||||
|
||||
|
Reference in New Issue
Block a user