diff --git a/csdr/csdr.py b/csdr/csdr.py index a95448b..ad4d344 100644 --- a/csdr/csdr.py +++ b/csdr/csdr.py @@ -198,10 +198,7 @@ class dsp(object): "csdr limit_ff", ] chain += last_decimation_block - chain += [ - "csdr deemphasis_wfm_ff {audio_rate} {wfm_deemphasis_tau}", - "csdr convert_f_s16" - ] + chain += ["csdr deemphasis_wfm_ff {audio_rate} {wfm_deemphasis_tau}", "csdr convert_f_s16"] elif self.isDigitalVoice(which): chain += ["csdr fmdemod_quadri_cf"] chain += last_decimation_block @@ -460,7 +457,9 @@ class dsp(object): def set_secondary_offset_freq(self, value): self.secondary_offset_freq = value if self.secondary_processes_running and self.has_pipe("secondary_shift_pipe"): - self.pipes["secondary_shift_pipe"].write("%g\n" % (-float(self.secondary_offset_freq) / self.if_samp_rate())) + self.pipes["secondary_shift_pipe"].write( + "%g\n" % (-float(self.secondary_offset_freq) / self.if_samp_rate()) + ) def stop_secondary_demodulator(self): if not self.secondary_processes_running: @@ -581,7 +580,7 @@ class dsp(object): demodulator = self.get_secondary_demodulator() return demodulator in ["ft8", "wspr", "jt65", "jt9", "ft4", "fst4", "fst4w"] - def isJs8(self, demodulator = None): + def isJs8(self, demodulator=None): if demodulator is None: demodulator = self.get_secondary_demodulator() return demodulator == "js8" @@ -689,7 +688,11 @@ class dsp(object): def set_squelch_level(self, squelch_level): self.squelch_level = squelch_level # no squelch required on digital voice modes - actual_squelch = -150 if self.isDigitalVoice() or self.isPacket() or self.isPocsag() or self.isFreeDV() else self.squelch_level + actual_squelch = ( + -150 + if self.isDigitalVoice() or self.isPacket() or self.isPocsag() or self.isFreeDV() + else self.squelch_level + ) if self.running: self.pipes["squelch_pipe"].write("%g\n" % (self.convertToLinear(actual_squelch))) @@ -842,6 +845,7 @@ class dsp(object): self.start_secondary_demodulator() if self.has_pipe("smeter_pipe"): + def read_smeter(): raw = self.pipes["smeter_pipe"].readline() if len(raw) == 0: @@ -851,6 +855,7 @@ class dsp(object): self.output.send_output("smeter", read_smeter) if self.has_pipe("meta_pipe"): + def read_meta(): raw = self.pipes["meta_pipe"].readline() if len(raw) == 0: diff --git a/csdr/pipe.py b/csdr/pipe.py index f915aef..025e287 100644 --- a/csdr/pipe.py +++ b/csdr/pipe.py @@ -42,6 +42,7 @@ class Pipe(object): immediately here), resulting in empty reads until data is available. This is handled specially in the ReadingPipe class. """ + def opener(path, flags): fd = os.open(path, flags | os.O_NONBLOCK) os.set_blocking(fd, True) @@ -88,7 +89,7 @@ class WritingPipe(Pipe): except OSError as error: # ENXIO = FIFO has not been opened for reading if error.errno == 6: - time.sleep(.1) + time.sleep(0.1) retries += 1 else: raise diff --git a/owrx/__main__.py b/owrx/__main__.py index 908767f..1903d8b 100644 --- a/owrx/__main__.py +++ b/owrx/__main__.py @@ -40,9 +40,7 @@ Support and info: https://groups.io/g/openwebrx configErrors = Config.validateConfig() if configErrors: - logger.error( - "your configuration contains errors. please address the following errors:" - ) + logger.error("your configuration contains errors. please address the following errors:") for e in configErrors: logger.error(e) return diff --git a/owrx/audio.py b/owrx/audio.py index 9a5b07f..fd57262 100644 --- a/owrx/audio.py +++ b/owrx/audio.py @@ -69,7 +69,9 @@ class DecoderQueue(Queue): with DecoderQueue.creationLock: if DecoderQueue.sharedInstance is None: pm = Config.get() - DecoderQueue.sharedInstance = DecoderQueue(maxsize=pm["decoding_queue_length"], workers=pm["decoding_queue_workers"]) + DecoderQueue.sharedInstance = DecoderQueue( + maxsize=pm["decoding_queue_length"], workers=pm["decoding_queue_workers"] + ) return DecoderQueue.sharedInstance @staticmethod diff --git a/owrx/bands.py b/owrx/bands.py index 89bf293..5062202 100644 --- a/owrx/bands.py +++ b/owrx/bands.py @@ -17,7 +17,7 @@ class Band(object): for (mode, freqs) in dict["frequencies"].items(): if mode not in availableModes: logger.info( - "Modulation \"{mode}\" is not available, bandplan bookmark will not be displayed".format( + 'Modulation "{mode}" is not available, bandplan bookmark will not be displayed'.format( mode=mode ) ) diff --git a/owrx/config.py b/owrx/config.py index 7c084a3..f668f8e 100644 --- a/owrx/config.py +++ b/owrx/config.py @@ -112,9 +112,7 @@ class Config: @staticmethod def validateConfig(): pm = Config.get() - errors = [ - Config.checkTempDirectory(pm) - ] + errors = [Config.checkTempDirectory(pm)] return [e for e in errors if e is not None] diff --git a/owrx/controllers/__init__.py b/owrx/controllers/__init__.py index 8d227c3..e1b5fbd 100644 --- a/owrx/controllers/__init__.py +++ b/owrx/controllers/__init__.py @@ -7,7 +7,9 @@ class Controller(object): self.request = request self.options = options - def send_response(self, content, code=200, content_type="text/html", last_modified: datetime = None, max_age=None, headers=None): + def send_response( + self, content, code=200, content_type="text/html", last_modified: datetime = None, max_age=None, headers=None + ): self.handler.send_response(code) if headers is None: headers = {} @@ -27,7 +29,7 @@ class Controller(object): def send_redirect(self, location, code=303, cookies=None): self.handler.send_response(code) if cookies is not None: - self.handler.send_header("Set-Cookie", cookies.output(header='')) + self.handler.send_header("Set-Cookie", cookies.output(header="")) self.handler.send_header("Location", location) self.handler.end_headers() diff --git a/owrx/controllers/assets.py b/owrx/controllers/assets.py index 7563325..803dec9 100644 --- a/owrx/controllers/assets.py +++ b/owrx/controllers/assets.py @@ -13,9 +13,9 @@ logger = logging.getLogger(__name__) class GzipMixin(object): - def send_response(self, content, headers=None, content_type="text/html", *args, **kwargs): + def send_response(self, content, headers=None, content_type="text/html", *args, **kwargs): if self.zipable(content_type) and "accept-encoding" in self.request.headers: - accepted = [s.strip().lower() for s in self.request.headers['accept-encoding'].split(",")] + accepted = [s.strip().lower() for s in self.request.headers["accept-encoding"].split(",")] if "gzip" in accepted: if type(content) == str: content = content.encode() @@ -26,11 +26,7 @@ class GzipMixin(object): super().send_response(content, headers=headers, content_type=content_type, *args, **kwargs) def zipable(self, content_type): - types = [ - "application/javascript", - "text/css", - "text/html" - ] + types = ["application/javascript", "text/css", "text/html"] return content_type in types def gzip(self, content): @@ -41,11 +37,11 @@ class ModificationAwareController(Controller, metaclass=ABCMeta): @abstractmethod def getModified(self, file): pass - + def wasModified(self, file): try: modified = self.getModified(file).replace(microsecond=0) - + if modified is not None and "If-Modified-Since" in self.handler.headers: client_modified = datetime.strptime( self.handler.headers["If-Modified-Since"], "%a, %d %b %Y %H:%M:%S %Z" @@ -54,7 +50,7 @@ class ModificationAwareController(Controller, metaclass=ABCMeta): return False except FileNotFoundError: pass - + return True @@ -143,7 +139,7 @@ class CompiledAssetsController(GzipMixin, ModificationAwareController): "lib/settings/Input.js", "lib/settings/SdrDevice.js", "settings.js", - ] + ], } def indexAction(self): diff --git a/owrx/controllers/receiverid.py b/owrx/controllers/receiverid.py index 667c6be..10c7361 100644 --- a/owrx/controllers/receiverid.py +++ b/owrx/controllers/receiverid.py @@ -8,15 +8,19 @@ class ReceiverIdController(Controller): super().__init__(handler, request, options) self.authHeader = None - def send_response(self, content, code=200, content_type="text/html", last_modified: datetime = None, max_age=None, headers=None): + def send_response( + self, content, code=200, content_type="text/html", last_modified: datetime = None, max_age=None, headers=None + ): if self.authHeader is not None: if headers is None: headers = {} - headers['Authorization'] = self.authHeader - super().send_response(content, code=code, content_type=content_type, last_modified=last_modified, max_age=max_age, headers=headers) + headers["Authorization"] = self.authHeader + super().send_response( + content, code=code, content_type=content_type, last_modified=last_modified, max_age=max_age, headers=headers + ) pass def handle_request(self): if "Authorization" in self.request.headers: - self.authHeader = ReceiverId.getResponseHeader(self.request.headers['Authorization']) + self.authHeader = ReceiverId.getResponseHeader(self.request.headers["Authorization"]) super().handle_request() diff --git a/owrx/controllers/settings.py b/owrx/controllers/settings.py index 368a167..cd68549 100644 --- a/owrx/controllers/settings.py +++ b/owrx/controllers/settings.py @@ -69,12 +69,16 @@ class SdrSettingsController(AdminController): {form} - """.format(device_name=config["name"], form=self.render_form(device_id, config)) + """.format( + device_name=config["name"], form=self.render_form(device_id, config) + ) def render_form(self, device_id, config): return """
- """.format(device_id=device_id, formdata=quote(json.dumps(config))) + """.format( + device_id=device_id, formdata=quote(json.dumps(config)) + ) def indexAction(self): self.serve_template("sdrsettings.html", **self.template_variables()) @@ -119,12 +123,18 @@ class GeneralSettingsController(AdminController): DropdownInput( "audio_compression", "Audio compression", - options=[Option("adpcm", "ADPCM"), Option("none", "None"),], + options=[ + Option("adpcm", "ADPCM"), + Option("none", "None"), + ], ), DropdownInput( "fft_compression", "Waterfall compression", - options=[Option("adpcm", "ADPCM"), Option("none", "None"),], + options=[ + Option("adpcm", "ADPCM"), + Option("none", "None"), + ], ), ), Section( @@ -196,10 +206,7 @@ class GeneralSettingsController(AdminController): "Js8Call decoding depth", infotext="A higher decoding depth will allow more results, but will also consume more cpu", ), - Js8ProfileCheckboxInput( - "js8_enabled_profiles", - "Js8Call enabled modes" - ), + Js8ProfileCheckboxInput("js8_enabled_profiles", "Js8Call enabled modes"), ), Section( "Background decoding", @@ -269,9 +276,7 @@ class GeneralSettingsController(AdminController): def processFormData(self): data = parse_qs(self.get_body().decode("utf-8")) - data = { - k: v for i in GeneralSettingsController.sections for k, v in i.parse(data).items() - } + data = {k: v for i in GeneralSettingsController.sections for k, v in i.parse(data).items()} config = Config.get() for k, v in data.items(): config[k] = v diff --git a/owrx/controllers/status.py b/owrx/controllers/status.py index 9e6a820..9100b34 100644 --- a/owrx/controllers/status.py +++ b/owrx/controllers/status.py @@ -22,7 +22,7 @@ class StatusController(ReceiverIdController): "name": receiver.getName(), # TODO would be better to have types from the config here "type": type(receiver).__name__, - "profiles": [self.getProfileStats(p) for p in receiver.getProfiles().values()] + "profiles": [self.getProfileStats(p) for p in receiver.getProfiles().values()], } return stats @@ -38,6 +38,6 @@ class StatusController(ReceiverIdController): }, "max_clients": pm["max_clients"], "version": openwebrx_version, - "sdrs": [self.getReceiverStats(r) for r in SdrService.getSources().values()] + "sdrs": [self.getReceiverStats(r) for r in SdrService.getSources().values()], } self.send_response(json.dumps(status), content_type="application/json") diff --git a/owrx/feature.py b/owrx/feature.py index 1a37494..8c940d2 100644 --- a/owrx/feature.py +++ b/owrx/feature.py @@ -152,7 +152,14 @@ class FeatureDetector(object): # prevent X11 programs from opening windows if called from a GUI shell env.pop("DISPLAY", None) try: - process = subprocess.Popen(cmd, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, cwd=tmp_dir, env=env) + process = subprocess.Popen( + cmd, + stdin=subprocess.DEVNULL, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + cwd=tmp_dir, + env=env, + ) rc = process.wait() if expected_result is None: return rc != 32512 @@ -214,7 +221,6 @@ class FeatureDetector(object): """ return self.command_is_runnable("perseustest -h") - def has_digiham(self): """ To use digital voice modes, the digiham package is required. You can find the package and installation @@ -547,4 +553,4 @@ class FeatureDetector(object): You can find more information [here](https://github.com/jketterl/eb200_connector). """ - return self._check_connector("eb200_connector") \ No newline at end of file + return self._check_connector("eb200_connector") diff --git a/owrx/form/__init__.py b/owrx/form/__init__.py index 7f59bf5..8b1fd9f 100644 --- a/owrx/form/__init__.py +++ b/owrx/form/__init__.py @@ -10,9 +10,7 @@ class Input(ABC): self.infotext = infotext def bootstrap_decorate(self, input): - infotext = ( - "{text}".format(text=self.infotext) if self.infotext else "" - ) + infotext = "{text}".format(text=self.infotext) if self.infotext else "" return """
@@ -108,9 +106,7 @@ class LocationInput(Input): ) def parse(self, data): - return { - self.id: {k: float(data["{0}-{1}".format(self.id, k)][0]) for k in ["lat", "lon"]} - } + return {self.id: {k: float(data["{0}-{1}".format(self.id, k)][0]) for k in ["lat", "lon"]}} class TextAreaInput(Input): @@ -195,9 +191,7 @@ class MultiCheckboxInput(Input): class ServicesCheckboxInput(MultiCheckboxInput): def __init__(self, id, label, infotext=None): - services = [ - Option(s.modulation, s.name) for s in Modes.getAvailableServices() - ] + services = [Option(s.modulation, s.name) for s in Modes.getAvailableServices()] super().__init__(id, label, services, infotext) diff --git a/owrx/http.py b/owrx/http.py index 538bec9..743f2c9 100644 --- a/owrx/http.py +++ b/owrx/http.py @@ -1,14 +1,6 @@ from owrx.controllers.status import StatusController -from owrx.controllers.template import ( - IndexController, - MapController, - FeatureController -) -from owrx.controllers.assets import ( - OwrxAssetsController, - AprsSymbolsController, - CompiledAssetsController -) +from owrx.controllers.template import IndexController, MapController, FeatureController +from owrx.controllers.assets import OwrxAssetsController, AprsSymbolsController, CompiledAssetsController from owrx.controllers.websocket import WebSocketController from owrx.controllers.api import ApiController from owrx.controllers.metrics import MetricsController @@ -109,7 +101,9 @@ class Router(object): StaticRoute("/metrics", MetricsController), StaticRoute("/settings", SettingsController), StaticRoute("/generalsettings", GeneralSettingsController), - StaticRoute("/generalsettings", GeneralSettingsController, method="POST", options={"action": "processFormData"}), + StaticRoute( + "/generalsettings", GeneralSettingsController, method="POST", options={"action": "processFormData"} + ), StaticRoute("/sdrsettings", SdrSettingsController), StaticRoute("/login", SessionController, options={"action": "loginAction"}), StaticRoute("/login", SessionController, method="POST", options={"action": "processLoginAction"}), diff --git a/owrx/js8.py b/owrx/js8.py index 79e1850..caee60d 100644 --- a/owrx/js8.py +++ b/owrx/js8.py @@ -102,15 +102,17 @@ class Js8Parser(Parser): Map.getSharedInstance().updateLocation( frame.callsign, LocatorLocation(frame.grid), "JS8", self.band ) - ReportingEngine.getSharedInstance().spot({ - "callsign": frame.callsign, - "mode": "JS8", - "locator": frame.grid, - "freq": self.dial_freq + frame.freq, - "db": frame.db, - "timestamp": frame.timestamp, - "msg": str(frame) - }) + ReportingEngine.getSharedInstance().spot( + { + "callsign": frame.callsign, + "mode": "JS8", + "locator": frame.grid, + "freq": self.dial_freq + frame.freq, + "db": frame.db, + "timestamp": frame.timestamp, + "msg": str(frame), + } + ) except Exception: logger.exception("error while parsing js8 message") diff --git a/owrx/kiss.py b/owrx/kiss.py index bb20489..cae7394 100644 --- a/owrx/kiss.py +++ b/owrx/kiss.py @@ -13,6 +13,7 @@ TFESC = 0xDD FEET_PER_METER = 3.28084 + class DirewolfConfig(object): def getConfig(self, port, is_service): pm = Config.get() @@ -40,7 +41,7 @@ IGLOGIN {callsign} {password} ) if pm["aprs_igate_beacon"]: - #Format beacon lat/lon + # Format beacon lat/lon lat = pm["receiver_gps"]["lat"] lon = pm["receiver_gps"]["lon"] direction_ns = "N" if lat > 0 else "S" @@ -50,13 +51,13 @@ IGLOGIN {callsign} {password} lat = "{0:02d}^{1:05.2f}{2}".format(int(lat), (lat - int(lat)) * 60, direction_ns) lon = "{0:03d}^{1:05.2f}{2}".format(int(lon), (lon - int(lon)) * 60, direction_we) - #Format beacon details - symbol = str(pm["aprs_igate_symbol"]) if "aprs_igate_symbol" in pm else "R&" - gain = "GAIN=" + str(pm["aprs_igate_gain"]) if "aprs_igate_gain" in pm else "" - adir = "DIR=" + str(pm["aprs_igate_dir"]) if "aprs_igate_dir" in pm else "" - comment = str(pm["aprs_igate_comment"]) if "aprs_igate_comment" in pm else "\"OpenWebRX APRS gateway\"" + # Format beacon details + symbol = str(pm["aprs_igate_symbol"]) if "aprs_igate_symbol" in pm else "R&" + gain = "GAIN=" + str(pm["aprs_igate_gain"]) if "aprs_igate_gain" in pm else "" + adir = "DIR=" + str(pm["aprs_igate_dir"]) if "aprs_igate_dir" in pm else "" + comment = str(pm["aprs_igate_comment"]) if "aprs_igate_comment" in pm else '"OpenWebRX APRS gateway"' - #Convert height from meters to feet if specified + # Convert height from meters to feet if specified height = "" if "aprs_igate_height" in pm: try: @@ -64,18 +65,21 @@ IGLOGIN {callsign} {password} height_ft = round(height_m * FEET_PER_METER) height = "HEIGHT=" + str(height_ft) except: - logger.error("Cannot parse 'aprs_igate_height', expected float: " + str(pm["aprs_igate_height"])) + logger.error( + "Cannot parse 'aprs_igate_height', expected float: " + str(pm["aprs_igate_height"]) + ) - if((len(comment) > 0) and ((comment[0] != '"') or (comment[len(comment)-1] != '"'))): - comment = "\"" + comment + "\"" - elif(len(comment) == 0): - comment = "\"\"" + if (len(comment) > 0) and ((comment[0] != '"') or (comment[len(comment) - 1] != '"')): + comment = '"' + comment + '"' + elif len(comment) == 0: + comment = '""' pbeacon = "PBEACON sendto=IG delay=0:30 every=60:00 symbol={symbol} lat={lat} long={lon} {height} {gain} {adir} comment={comment}".format( - symbol=symbol, lat=lat, lon=lon, height=height, gain=gain, adir=adir, comment=comment ) + symbol=symbol, lat=lat, lon=lon, height=height, gain=gain, adir=adir, comment=comment + ) logger.info("APRS PBEACON String: " + pbeacon) - + config += "\n" + pbeacon + "\n" return config @@ -98,7 +102,7 @@ class KissClient(object): pass def __init__(self, port): - delay = .5 + delay = 0.5 retries = 0 while True: try: diff --git a/owrx/modes.py b/owrx/modes.py index 0fcf366..f544e19 100644 --- a/owrx/modes.py +++ b/owrx/modes.py @@ -60,24 +60,47 @@ class Modes(object): AnalogMode("usb", "USB", bandpass=Bandpass(300, 3000)), AnalogMode("cw", "CW", bandpass=Bandpass(700, 900)), AnalogMode("dmr", "DMR", bandpass=Bandpass(-4000, 4000), requirements=["digital_voice_digiham"], squelch=False), - AnalogMode("dstar", "D-Star", bandpass=Bandpass(-3250, 3250), requirements=["digital_voice_dsd"], squelch=False), + AnalogMode( + "dstar", "D-Star", bandpass=Bandpass(-3250, 3250), requirements=["digital_voice_dsd"], squelch=False + ), AnalogMode("nxdn", "NXDN", bandpass=Bandpass(-3250, 3250), requirements=["digital_voice_dsd"], squelch=False), AnalogMode("ysf", "YSF", bandpass=Bandpass(-4000, 4000), requirements=["digital_voice_digiham"], squelch=False), AnalogMode("m17", "M17", bandpass=Bandpass(-4000, 4000), requirements=["digital_voice_m17"], squelch=False), - AnalogMode("freedv", "FreeDV", bandpass=Bandpass(300, 3000), requirements=["digital_voice_freedv"], squelch=False), + AnalogMode( + "freedv", "FreeDV", bandpass=Bandpass(300, 3000), requirements=["digital_voice_freedv"], squelch=False + ), AnalogMode("drm", "DRM", bandpass=Bandpass(-5000, 5000), requirements=["drm"], squelch=False), DigitalMode("bpsk31", "BPSK31", underlying=["usb"]), DigitalMode("bpsk63", "BPSK63", underlying=["usb"]), - DigitalMode("ft8", "FT8", underlying=["usb"], bandpass=Bandpass(0, 3000), requirements=["wsjt-x"], service=True), - DigitalMode("ft4", "FT4", underlying=["usb"], bandpass=Bandpass(0, 3000), requirements=["wsjt-x"], service=True), - DigitalMode("jt65", "JT65", underlying=["usb"], bandpass=Bandpass(0, 3000), requirements=["wsjt-x"], service=True), - DigitalMode("jt9", "JT9", underlying=["usb"], bandpass=Bandpass(0, 3000), requirements=["wsjt-x"], service=True), + DigitalMode( + "ft8", "FT8", underlying=["usb"], bandpass=Bandpass(0, 3000), requirements=["wsjt-x"], service=True + ), + DigitalMode( + "ft4", "FT4", underlying=["usb"], bandpass=Bandpass(0, 3000), requirements=["wsjt-x"], service=True + ), + DigitalMode( + "jt65", "JT65", underlying=["usb"], bandpass=Bandpass(0, 3000), requirements=["wsjt-x"], service=True + ), + DigitalMode( + "jt9", "JT9", underlying=["usb"], bandpass=Bandpass(0, 3000), requirements=["wsjt-x"], service=True + ), DigitalMode( "wspr", "WSPR", underlying=["usb"], bandpass=Bandpass(1350, 1650), requirements=["wsjt-x"], service=True ), - DigitalMode("fst4", "FST4", underlying=["usb"], bandpass=Bandpass(0, 3000), requirements=["wsjt-x-2-3"], service=True), - DigitalMode("fst4w", "FST4W", underlying=["usb"], bandpass=Bandpass(1350, 1650), requirements=["wsjt-x-2-3"], service=True), - DigitalMode("js8", "JS8Call", underlying=["usb"], bandpass=Bandpass(0, 3000), requirements=["js8call"], service=True), + DigitalMode( + "fst4", "FST4", underlying=["usb"], bandpass=Bandpass(0, 3000), requirements=["wsjt-x-2-3"], service=True + ), + DigitalMode( + "fst4w", + "FST4W", + underlying=["usb"], + bandpass=Bandpass(1350, 1650), + requirements=["wsjt-x-2-3"], + service=True, + ), + DigitalMode( + "js8", "JS8Call", underlying=["usb"], bandpass=Bandpass(0, 3000), requirements=["js8call"], service=True + ), DigitalMode( "packet", "Packet", diff --git a/owrx/pskreporter.py b/owrx/pskreporter.py index 533a251..4106648 100644 --- a/owrx/pskreporter.py +++ b/owrx/pskreporter.py @@ -150,10 +150,10 @@ class Uploader(object): # id [0x00, 0x03] # length - + list(length.to_bytes(2, 'big')) + + list(length.to_bytes(2, "big")) + Uploader.receieverDelimiter # number of fields - + list(num_fields.to_bytes(2, 'big')) + + list(num_fields.to_bytes(2, "big")) # padding + [0x00, 0x00] # receiverCallsign @@ -163,9 +163,7 @@ class Uploader(object): # decodingSoftware + [0x80, 0x08, 0xFF, 0xFF, 0x00, 0x00, 0x76, 0x8F] # antennaInformation - + ( - [0x80, 0x09, 0xFF, 0xFF, 0x00, 0x00, 0x76, 0x8F] if with_antenna else [] - ) + + ([0x80, 0x09, 0xFF, 0xFF, 0x00, 0x00, 0x76, 0x8F] if with_antenna else []) # padding + [0x00, 0x00] ) diff --git a/owrx/receiverid.py b/owrx/receiverid.py index c7b12b7..e21760a 100644 --- a/owrx/receiverid.py +++ b/owrx/receiverid.py @@ -77,6 +77,7 @@ class ReceiverId(object): return Key(keyString) except KeyException as e: logger.error(e) + config = Config.get() if "receiver_keys" not in config or config["receiver_keys"] is None: return None diff --git a/owrx/reporting.py b/owrx/reporting.py index faa427c..32e996c 100644 --- a/owrx/reporting.py +++ b/owrx/reporting.py @@ -40,10 +40,12 @@ class ReportingEngine(object): if "pskreporter_enabled" in config and config["pskreporter_enabled"]: # inline import due to circular dependencies from owrx.pskreporter import PskReporter + self.reporters += [PskReporter()] if "wsprnet_enabled" in config and config["wsprnet_enabled"]: # inline import due to circular dependencies from owrx.wsprnet import WsprnetReporter + self.reporters += [WsprnetReporter()] def stop(self): diff --git a/owrx/service/__init__.py b/owrx/service/__init__.py index 81d0877..540e3c3 100644 --- a/owrx/service/__init__.py +++ b/owrx/service/__init__.py @@ -137,9 +137,7 @@ class ServiceHandler(SdrSourceEventClient): dials = [ dial - for dial in Bandplan.getSharedInstance().collectDialFrequencies( - frequency_range - ) + for dial in Bandplan.getSharedInstance().collectDialFrequencies(frequency_range) if self.isSupported(dial["mode"]) ] @@ -150,16 +148,12 @@ class ServiceHandler(SdrSourceEventClient): groups = self.optimizeResampling(dials, sr) if groups is None: for dial in dials: - self.services.append( - self.setupService(dial["mode"], dial["frequency"], self.source) - ) + self.services.append(self.setupService(dial["mode"], dial["frequency"], self.source)) else: for group in groups: cf = self.get_center_frequency(group) bw = self.get_bandwidth(group) - logger.debug( - "group center frequency: {0}, bandwidth: {1}".format(cf, bw) - ) + logger.debug("group center frequency: {0}, bandwidth: {1}".format(cf, bw)) resampler_props = PropertyLayer() resampler_props["center_freq"] = cf resampler_props["samp_rate"] = bw @@ -167,11 +161,7 @@ class ServiceHandler(SdrSourceEventClient): resampler.start() for dial in group: - self.services.append( - self.setupService( - dial["mode"], dial["frequency"], resampler - ) - ) + self.services.append(self.setupService(dial["mode"], dial["frequency"], resampler)) # resampler goes in after the services since it must not be shutdown as long as the services are still running self.services.append(resampler) @@ -238,9 +228,7 @@ class ServiceHandler(SdrSourceEventClient): 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"]) - ) + logger.debug("splits: {0}, total: {1}".format(r["num_splits"], r["total_bandwidth"])) best = results[0] if best["num_splits"] is None: @@ -267,7 +255,7 @@ class ServiceHandler(SdrSourceEventClient): d.set_secondary_demodulator(mode) d.set_audio_compression("none") d.set_samp_rate(source.getProps()["samp_rate"]) - d.set_temporary_directory(Config.get()['temporary_directory']) + d.set_temporary_directory(Config.get()["temporary_directory"]) d.set_service() d.start() return d diff --git a/owrx/service/schedule.py b/owrx/service/schedule.py index 141962d..c024d33 100644 --- a/owrx/service/schedule.py +++ b/owrx/service/schedule.py @@ -68,6 +68,7 @@ class DatetimeScheduleEntry(ScheduleEntry): def getNextActivation(self): return self.startTime + class Schedule(ABC): @staticmethod def parse(props): @@ -140,7 +141,7 @@ class DaylightSchedule(TimerangeSchedule): degtorad = math.pi / 180 radtodeg = 180 / math.pi - #Number of days since 01/01 + # Number of days since 01/01 days = date.timetuple().tm_yday # Longitudinal correction diff --git a/owrx/source/__init__.py b/owrx/source/__init__.py index 39c143d..111f507 100644 --- a/owrx/source/__init__.py +++ b/owrx/source/__init__.py @@ -82,17 +82,17 @@ class SdrSource(ABC): for id, p in self.props["profiles"].items(): props.replaceLayer(0, self._getProfilePropertyLayer(p)) if "center_freq" not in props: - logger.warning("Profile \"%s\" does not specify a center_freq", id) + logger.warning('Profile "%s" does not specify a center_freq', id) continue if "samp_rate" not in props: - logger.warning("Profile \"%s\" does not specify a samp_rate", id) + logger.warning('Profile "%s" does not specify a samp_rate', id) continue if "start_freq" in props: start_freq = props["start_freq"] srh = props["samp_rate"] / 2 center_freq = props["center_freq"] if start_freq < center_freq - srh or start_freq > center_freq + srh: - logger.warning("start_freq for profile \"%s\" is out of range", id) + logger.warning('start_freq for profile "%s" is out of range', id) def _getProfilePropertyLayer(self, profile): layer = PropertyLayer() diff --git a/owrx/source/connector.py b/owrx/source/connector.py index 40095b0..8789cbe 100644 --- a/owrx/source/connector.py +++ b/owrx/source/connector.py @@ -15,18 +15,22 @@ class ConnectorSource(SdrSource): super().__init__(id, props) def getCommandMapper(self): - return super().getCommandMapper().setMappings( - { - "samp_rate": Option("-s"), - "tuner_freq": Option("-f"), - "port": Option("-p"), - "controlPort": Option("-c"), - "device": Option("-d"), - "iqswap": Flag("-i"), - "rtltcp_compat": Option("-r"), - "ppm": Option("-P"), - "rf_gain": Option("-g"), - } + return ( + super() + .getCommandMapper() + .setMappings( + { + "samp_rate": Option("-s"), + "tuner_freq": Option("-f"), + "port": Option("-p"), + "controlPort": Option("-c"), + "device": Option("-d"), + "iqswap": Flag("-i"), + "rtltcp_compat": Option("-r"), + "ppm": Option("-P"), + "rf_gain": Option("-g"), + } + ) ) def sendControlMessage(self, changes): diff --git a/owrx/source/direct.py b/owrx/source/direct.py index cd36b55..e5d0024 100644 --- a/owrx/source/direct.py +++ b/owrx/source/direct.py @@ -32,11 +32,14 @@ class DirectSource(SdrSource, metaclass=ABCMeta): "These depend on nmux_memory and samp_rate options in config_webrx.py" ) - return ["nmux --bufsize %d --bufcnt %d --port %d --address 127.0.0.1" % ( - nmux_bufsize, - nmux_bufcnt, - self.port, - )] + return [ + "nmux --bufsize %d --bufcnt %d --port %d --address 127.0.0.1" + % ( + nmux_bufsize, + nmux_bufcnt, + self.port, + ) + ] def getCommand(self): return super().getCommand() + self.getFormatConversion() + self.getNmuxCommand() diff --git a/owrx/source/eb200.py b/owrx/source/eb200.py index a234a59..50ef622 100644 --- a/owrx/source/eb200.py +++ b/owrx/source/eb200.py @@ -8,8 +8,10 @@ class Eb200Source(ConnectorSource): super() .getCommandMapper() .setBase("eb200_connector") - .setMappings({ - "long": Flag("-l"), - "remote": Argument(), - }) + .setMappings( + { + "long": Flag("-l"), + "remote": Argument(), + } + ) ) diff --git a/owrx/source/fifi_sdr.py b/owrx/source/fifi_sdr.py index badf3ac..5b51558 100644 --- a/owrx/source/fifi_sdr.py +++ b/owrx/source/fifi_sdr.py @@ -9,9 +9,13 @@ logger = logging.getLogger(__name__) class FifiSdrSource(DirectSource): def getCommandMapper(self): - return super().getCommandMapper().setBase("arecord").setMappings( - {"device": Option("-D"), "samp_rate": Option("-r")} - ).setStatic("-t raw -f S16_LE -c2 -") + return ( + super() + .getCommandMapper() + .setBase("arecord") + .setMappings({"device": Option("-D"), "samp_rate": Option("-r")}) + .setStatic("-t raw -f S16_LE -c2 -") + ) def getEventNames(self): return super().getEventNames() + ["device"] @@ -20,7 +24,7 @@ class FifiSdrSource(DirectSource): return ["csdr convert_s16_f", "csdr gain_ff 5"] def sendRockProgFrequency(self, frequency): - process = Popen(["rockprog", "--vco", "-w", "--freq={}".format(frequency / 1E6)]) + process = Popen(["rockprog", "--vco", "-w", "--freq={}".format(frequency / 1e6)]) process.communicate() rc = process.wait() if rc != 0: diff --git a/owrx/source/hackrf.py b/owrx/source/hackrf.py index a103218..9ced99e 100644 --- a/owrx/source/hackrf.py +++ b/owrx/source/hackrf.py @@ -8,4 +8,4 @@ class HackrfSource(SoapyConnectorSource): return mappings def getDriver(self): - return "hackrf" \ No newline at end of file + return "hackrf" diff --git a/owrx/source/hpsdr.py b/owrx/source/hpsdr.py index 50cac77..6d88c67 100644 --- a/owrx/source/hpsdr.py +++ b/owrx/source/hpsdr.py @@ -17,6 +17,7 @@ from owrx.command import Flag, Option # If you omit `remote` from config_webrx.py, hpsdrconnector will use the HPSDR discovery protocol # to find radios on your local network and will connect to the first radio it discovered. + class HpsdrSource(ConnectorSource): def getCommandMapper(self): return ( @@ -24,10 +25,11 @@ class HpsdrSource(ConnectorSource): .getCommandMapper() .setBase("hpsdrconnector") .setMappings( - { - "tuner_freq": Option("--frequency"), - "samp_rate": Option("--samplerate"), - "remote": Option("--radio"), - "rf_gain": Option("--gain"), - }) + { + "tuner_freq": Option("--frequency"), + "samp_rate": Option("--samplerate"), + "remote": Option("--radio"), + "rf_gain": Option("--gain"), + } + ) ) diff --git a/owrx/source/perseussdr.py b/owrx/source/perseussdr.py index bad4f38..1e2b8ec 100644 --- a/owrx/source/perseussdr.py +++ b/owrx/source/perseussdr.py @@ -17,15 +17,21 @@ from owrx.command import Flag, Option # floating points (option -p),no need for further conversions, # so the method getFormatConversion(self) is not implemented at all. + class PerseussdrSource(DirectSource): def getCommandMapper(self): - return super().getCommandMapper().setBase("perseustest -p -d -1 -a -t 0 -o - ").setMappings( - { - "samp_rate": Option("-s"), - "tuner_freq": Option("-f"), - "attenuator": Option("-u"), - "adc_preamp": Option("-m"), - "adc_dither": Option("-x"), - "wideband": Option("-w"), - } + return ( + super() + .getCommandMapper() + .setBase("perseustest -p -d -1 -a -t 0 -o - ") + .setMappings( + { + "samp_rate": Option("-s"), + "tuner_freq": Option("-f"), + "attenuator": Option("-u"), + "adc_preamp": Option("-m"), + "adc_dither": Option("-x"), + "wideband": Option("-w"), + } + ) ) diff --git a/owrx/source/rtl_tcp.py b/owrx/source/rtl_tcp.py index 03c3109..ba6ac1f 100644 --- a/owrx/source/rtl_tcp.py +++ b/owrx/source/rtl_tcp.py @@ -8,9 +8,11 @@ class RtlTcpSource(ConnectorSource): super() .getCommandMapper() .setBase("rtl_tcp_connector") - .setMappings({ - "bias_tee": Flag("-b"), - "direct_sampling": Option("-e"), - "remote": Argument(), - }) + .setMappings( + { + "bias_tee": Flag("-b"), + "direct_sampling": Option("-e"), + "remote": Argument(), + } + ) ) diff --git a/owrx/source/soapy.py b/owrx/source/soapy.py index 0c03a67..64c0713 100644 --- a/owrx/source/soapy.py +++ b/owrx/source/soapy.py @@ -5,11 +5,16 @@ from .connector import ConnectorSource class SoapyConnectorSource(ConnectorSource, metaclass=ABCMeta): def getCommandMapper(self): - return super().getCommandMapper().setBase("soapy_connector").setMappings( - { - "antenna": Option("-a"), - "soapy_settings": Option("-t"), - } + return ( + super() + .getCommandMapper() + .setBase("soapy_connector") + .setMappings( + { + "antenna": Option("-a"), + "soapy_settings": Option("-t"), + } + ) ) """ diff --git a/owrx/users.py b/owrx/users.py index 43e0865..0398108 100644 --- a/owrx/users.py +++ b/owrx/users.py @@ -29,7 +29,7 @@ class Password(ABC): class CleartextPassword(Password): def is_valid(self, inp: str): - return self.pwinfo['value'] == inp + return self.pwinfo["value"] == inp class User(object): diff --git a/owrx/wsjt.py b/owrx/wsjt.py index c432831..fb8df5b 100644 --- a/owrx/wsjt.py +++ b/owrx/wsjt.py @@ -99,7 +99,7 @@ class Ft4Profile(WsjtProfile): class Fst4Profile(WsjtProfile): - availableIntervals = [15, 30, 60, 120, 300, 900, 1800] + availableIntervals = [15, 30, 60, 120, 300, 900, 1800] def __init__(self, interval): self.interval = interval @@ -208,7 +208,7 @@ class Decoder(ABC): dateformat = self.profile.getTimestampFormat() remain = instring[len(dateformat) + 1:] try: - ts = datetime.strptime(instring[0:len(dateformat)], dateformat) + ts = datetime.strptime(instring[0: len(dateformat)], dateformat) return remain, int( datetime.combine(datetime.utcnow().date(), ts.time()).replace(tzinfo=timezone.utc).timestamp() * 1000 ) diff --git a/owrx/wsprnet.py b/owrx/wsprnet.py index 35bbe44..aff4fa8 100644 --- a/owrx/wsprnet.py +++ b/owrx/wsprnet.py @@ -43,24 +43,26 @@ class Worker(threading.Thread): # function=wspr&date=210114&time=1732&sig=-15&dt=0.5&drift=0&tqrg=7.040019&tcall=DF2UU&tgrid=JN48&dbm=37&version=2.3.0-rc3&rcall=DD5JFK&rgrid=JN58SC&rqrg=7.040047&mode=2 # {'timestamp': 1610655960000, 'db': -23.0, 'dt': 0.3, 'freq': 7040048, 'drift': -1, 'msg': 'LA3JJ JO59 37', 'callsign': 'LA3JJ', 'locator': 'JO59', 'mode': 'WSPR'} date = datetime.fromtimestamp(spot["timestamp"] / 1000, tz=timezone.utc) - data = parse.urlencode({ - "function": "wspr", - "date": date.strftime("%y%m%d"), - "time": date.strftime("%H%M"), - "sig": spot["db"], - "dt": spot["dt"], - # FST4W does not have drift - "drift": spot["drift"] if "drift" in spot else 0, - "tqrg": spot["freq"] / 1E6, - "tcall": spot["callsign"], - "tgrid": spot["locator"], - "dbm": spot["dbm"], - "version": openwebrx_version, - "rcall": self.callsign, - "rgrid": self.locator, - # mode 2 = WSPR 2 minutes - "mode": self._getMode(spot) - }).encode() + data = parse.urlencode( + { + "function": "wspr", + "date": date.strftime("%y%m%d"), + "time": date.strftime("%H%M"), + "sig": spot["db"], + "dt": spot["dt"], + # FST4W does not have drift + "drift": spot["drift"] if "drift" in spot else 0, + "tqrg": spot["freq"] / 1e6, + "tcall": spot["callsign"], + "tgrid": spot["locator"], + "dbm": spot["dbm"], + "version": openwebrx_version, + "rcall": self.callsign, + "rgrid": self.locator, + # mode 2 = WSPR 2 minutes + "mode": self._getMode(spot), + } + ).encode() request.urlopen("http://wsprnet.org/post/", data) diff --git a/setup.py b/setup.py index e8d7524..076750c 100644 --- a/setup.py +++ b/setup.py @@ -6,12 +6,24 @@ try: from setuptools import find_namespace_packages except ImportError: from setuptools import PEP420PackageFinder + find_namespace_packages = PEP420PackageFinder.find setup( name="OpenWebRX", version=str(looseversion), - packages=find_namespace_packages(include=["owrx", "owrx.source", "owrx.service", "owrx.controllers", "owrx.property", "owrx.form", "csdr", "htdocs"]), + packages=find_namespace_packages( + include=[ + "owrx", + "owrx.source", + "owrx.service", + "owrx.controllers", + "owrx.property", + "owrx.form", + "csdr", + "htdocs", + ] + ), package_data={"htdocs": [f[len("htdocs/") :] for f in glob("htdocs/**/*", recursive=True)]}, entry_points={"console_scripts": ["openwebrx=owrx.__main__:main"]}, url="https://www.openwebrx.de/", diff --git a/test/property/test_property_filter.py b/test/property/test_property_filter.py index db6dfd3..0c9ac81 100644 --- a/test/property/test_property_filter.py +++ b/test/property/test_property_filter.py @@ -4,7 +4,6 @@ from owrx.property import PropertyLayer, PropertyFilter class PropertyFilterTest(TestCase): - def testPassesProperty(self): pm = PropertyLayer() pm["testkey"] = "testvalue"