示例#1
0
def start_receiver():
    print("""

OpenWebRX - Open Source SDR Web App for Everyone!  | for license see LICENSE file in the package
_________________________________________________________________________________________________

Author contact info:    Jakob Ketterl, DD5JFK <*****@*****.**>
Documentation:          https://github.com/jketterl/openwebrx/wiki
Support and info:       https://groups.io/g/openwebrx

    """)

    logger.info(
        "OpenWebRX version {0} starting up...".format(openwebrx_version))

    for sig in [signal.SIGINT, signal.SIGTERM]:
        signal.signal(sig, handleSignal)

    # config warmup
    Config.validateConfig()
    coreConfig = CoreConfig()

    featureDetector = FeatureDetector()
    failed = featureDetector.get_failed_requirements("core")
    if failed:
        logger.error(
            "you are missing required dependencies to run openwebrx. "
            "please check that the following core requirements are installed and up to date: %s",
            ", ".join(failed))
        for f in failed:
            description = featureDetector.get_requirement_description(f)
            if description:
                logger.error("description for %s:\n%s", f, description)
        return 1

    # Get error messages about unknown / unavailable features as soon as possible
    # start up "always-on" sources right away
    SdrService.getAllSources()

    Services.start()

    try:
        server = ThreadedHttpServer(("0.0.0.0", coreConfig.get_web_port()),
                                    RequestHandler)
        server.serve_forever()
    except SignalException:
        pass

    WebSocketConnection.closeAll()
    Services.stop()
    SdrService.stopAllSources()
    ReportingEngine.stopAll()
    DecoderQueue.stopAll()

    return 0
示例#2
0
def main():
    print("""

OpenWebRX - Open Source SDR Web App for Everyone!  | for license see LICENSE file in the package
_________________________________________________________________________________________________

Author contact info:    Jakob Ketterl, DD5JFK <*****@*****.**>
Documentation:          https://github.com/jketterl/openwebrx/wiki
Support and info:       https://groups.io/g/openwebrx

    """)

    logger.info(
        "OpenWebRX version {0} starting up...".format(openwebrx_version))

    pm = Config.get()

    configErrors = Config.validateConfig()
    if configErrors:
        logger.error(
            "your configuration contains errors. please address the following errors:"
        )
        for e in configErrors:
            logger.error(e)
        return

    featureDetector = FeatureDetector()
    if not featureDetector.is_available("core"):
        logger.error(
            "you are missing required dependencies to run openwebrx. "
            "please check that the following core requirements are installed and up to date:"
        )
        logger.error(", ".join(featureDetector.get_requirements("core")))
        return

    # Get error messages about unknown / unavailable features as soon as possible
    SdrService.loadProps()

    Services.start()

    try:
        server = ThreadedHttpServer(("0.0.0.0", pm["web_port"]),
                                    RequestHandler)
        server.serve_forever()
    except KeyboardInterrupt:
        WebSocketConnection.closeAll()
        Services.stop()
        PskReporter.stop()
示例#3
0
 def start():
     if not Config.get()["services_enabled"]:
         return
     for source in SdrService.getSources().values():
         props = source.getProps()
         if "services" not in props or props["services"] is not False:
             Services.handlers.append(ServiceHandler(source))
示例#4
0
    def __init__(self, conn):
        super().__init__(conn)

        pm = Config.get()
        self.write_config(pm.filter("google_maps_api_key", "receiver_gps", "map_position_retention_time").__dict__())

        Map.getSharedInstance().addClient(self)
示例#5
0
    def enrich(self, meta, callback):
        config_key = "digital_voice_{}_id_lookup".format(self.mode)
        if not Config.get()[config_key]:
            return meta
        if "source" not in meta:
            return meta
        id = int(meta["source"])
        cache = RadioIDCache.getSharedInstance()
        if not cache.isValid(self.mode, id):
            if id not in self.threads:
                self.threads[id] = threading.Thread(target=self._fillCache, args=[id], daemon=True)
                self.threads[id].start()
            if id not in self.callbacks:
                self.callbacks[id] = []

            def onFinish(data):
                if data is not None:
                    meta["additional"] = data
                callback(meta)

            self.callbacks[id].append(onFinish)
            return meta
        data = cache.get(self.mode, id)
        if data is not None:
            meta["additional"] = data
        return meta
示例#6
0
 def start():
     config = Config.get()
     config.wireProperty("services_enabled", Services._receiveEnabledEvent)
     activeSources = SdrService.getActiveSources()
     activeSources.wire(Services._receiveDeviceEvent)
     for key, source in activeSources.items():
         Services.schedulers[key] = ServiceScheduler(source)
示例#7
0
    def handleSdrAvailable(self):
        # send initial config
        self.getDsp().setProperties(self.connectionProperties)

        stack = PropertyStack()
        stack.addLayer(0, self.sdr.getProps())
        stack.addLayer(1, Config.get())
        configProps = stack.filter(*OpenWebRxReceiverClient.config_keys)

        def sendConfig(key, value):
            config = configProps.__dict__()
            # TODO mathematical properties? hmmmm
            config["start_offset_freq"] = configProps["start_freq"] - configProps["center_freq"]
            # TODO this is a hack to support multiple sdrs
            config["sdr_id"] = self.sdr.getId()
            self.write_config(config)

            cf = configProps["center_freq"]
            srh = configProps["samp_rate"] / 2
            frequencyRange = (cf - srh, cf + srh)
            self.write_dial_frequendies(Bandplan.getSharedInstance().collectDialFrequencies(frequencyRange))
            bookmarks = [b.__dict__() for b in Bookmarks.getSharedInstance().getBookmarks(frequencyRange)]
            self.write_bookmarks(bookmarks)

        self.configSub = configProps.wire(sendConfig)
        sendConfig(None, None)
        self.__sendProfiles()

        self.sdr.addSpectrumClient(self)
示例#8
0
文件: assets.py 项目: jwt27/openwebrx
 def __init__(self, handler, request, options):
     pm = Config.get()
     path = pm["aprs_symbols_path"]
     if not path.endswith("/"):
         path += "/"
     self.path = path
     super().__init__(handler, request, options)
示例#9
0
 def getReceiverInformationHeader(self):
     pm = Config.get()
     with_antenna = "pskreporter_antenna_information" in pm and pm[
         "pskreporter_antenna_information"] is not None
     num_fields = 4 if with_antenna else 3
     length = 12 + num_fields * 8
     return bytes(
         # id
         [0x00, 0x03]
         # length
         + list(length.to_bytes(2, "big")) + Uploader.receieverDelimiter
         # number of fields
         + list(num_fields.to_bytes(2, "big"))
         # padding
         + [0x00, 0x00]
         # receiverCallsign
         + [0x80, 0x02, 0xFF, 0xFF, 0x00, 0x00, 0x76, 0x8F]
         # receiverLocator
         + [0x80, 0x04, 0xFF, 0xFF, 0x00, 0x00, 0x76, 0x8F]
         # decodingSoftware
         + [0x80, 0x08, 0xFF, 0xFF, 0x00, 0x00, 0x76, 0x8F]
         # antennaInformation
         + ([0x80, 0x09, 0xFF, 0xFF, 0x00, 0x00, 0x76, 0x8F]
            if with_antenna else [])
         # padding
         + [0x00, 0x00])
示例#10
0
 def decoding_depth(self):
     pm = Config.get()
     # return global default
     if "js8_decoding_depth" in pm:
         return pm["js8_decoding_depth"]
     # default when no setting is provided
     return 3
示例#11
0
文件: sdr.py 项目: jketterl/openwebrx
 def deleteProfile(self):
     if self.profile_id is None:
         return self.send_response("profile not found", code=404)
     config = Config.get()
     del self.device["profiles"][self.profile_id]
     config.store()
     return self.send_redirect("{}settings/sdr/{}".format(self.get_document_root(), quote(self.device_id)))
示例#12
0
文件: sdr.py 项目: jketterl/openwebrx
 def store(self):
     # need to overwrite the existing key in the config since the layering won't capture the changes otherwise
     config = Config.get()
     sdrs = config["sdrs"]
     sdrs[self.device_id] = self.device
     config["sdrs"] = sdrs
     super().store()
示例#13
0
    def getSunTimes(self, date):
        pm = Config.get()
        lat = pm["receiver_gps"]["lat"]
        lng = pm["receiver_gps"]["lon"]
        degtorad = math.pi / 180
        radtodeg = 180 / math.pi

        #Number of days since 01/01
        days = date.timetuple().tm_yday

        # Longitudinal correction
        longCorr = 4 * lng

        # calibrate for solstice
        b = 2 * math.pi * (days - 81) / 365

        # Equation of Time Correction
        eoTCorr = 9.87 * math.sin(2 * b) - 7.53 * math.cos(b) - 1.5 * math.sin(b)

        # Solar correction
        solarCorr = longCorr + eoTCorr

        # Solar declination
        declination = math.asin(math.sin(23.45 * degtorad) * math.sin(b))

        sunrise = 12 - math.acos(-math.tan(lat * degtorad) * math.tan(declination)) * radtodeg / 15 - solarCorr / 60
        sunset = 12 + math.acos(-math.tan(lat * degtorad) * math.tan(declination)) * radtodeg / 15 - solarCorr / 60

        midnight = datetime.combine(date, datetime.min.time())
        sunrise = midnight + timedelta(hours=sunrise)
        sunset = midnight + timedelta(hours=sunset)
        logger.debug("for {date} sunrise: {sunrise} sunset {sunset}".format(date=date, sunrise=sunrise, sunset=sunset))

        return sunrise, sunset
示例#14
0
 def uploadSpot(self, spot):
     config = Config.get()
     # 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": config["wsprnet_callsign"],
             "rgrid": Locator.fromCoordinates(config["receiver_gps"]),
             "mode": self._getMode(spot),
         }
     ).encode()
     request.urlopen("http://wsprnet.org/post/", data, timeout=60)
示例#15
0
 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":
         output = AprsServiceOutput(frequency)
     elif mode == "js8":
         output = Js8ServiceOutput(frequency)
     else:
         output = WsjtServiceOutput(frequency)
     d = dsp(output)
     d.nc_port = source.getPort()
     center_freq = source.getProps()["center_freq"]
     d.set_offset_freq(frequency - center_freq)
     d.set_center_freq(center_freq)
     if mode == "packet":
         d.set_demodulator("nfm")
         d.set_bpf(-4000, 4000)
     elif mode == "wspr":
         d.set_demodulator("usb")
         # WSPR only samples between 1400 and 1600 Hz
         d.set_bpf(1350, 1650)
     else:
         d.set_demodulator("usb")
         d.set_bpf(0, 3000)
     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_service()
     d.start()
     return d
示例#16
0
    def __init__(self, id, props):
        self.id = id

        self.commandMapper = None

        self.props = PropertyStack()
        # layer 0 reserved for profile properties
        self.props.addLayer(1, props)
        self.props.addLayer(2, Config.get())
        self.sdrProps = self.props.filter(*self.getEventNames())

        self.profile_id = None
        self.activateProfile()
        self.wireEvents()

        if "port" in props and props["port"] is not None:
            self.port = props["port"]
        else:
            self.port = getAvailablePort()
        self.monitor = None
        self.clients = []
        self.spectrumClients = []
        self.spectrumThread = None
        self.process = None
        self.modificationLock = threading.Lock()
        self.failed = False
        self.state = SdrSource.STATE_STOPPED
        self.busyState = SdrSource.BUSYSTATE_IDLE

        if self.isAlwaysOn():
            self.start()
示例#17
0
 def _start(self):
     self.running = True
     self.source.addClient(self)
     props = self.source.getProps()
     self.activitySub = props.filter("center_freq", "samp_rate").wire(self.onFrequencyChange)
     self.decodersSub = Config.get().wireProperty("services_decoders", self.onFrequencyChange)
     if self.source.isAvailable():
         self._scheduleServiceStartup()
示例#18
0
 def __init__(self):
     config = Config.get()
     if "waterfall_colors" in config and config["waterfall_colors"]:
         colors = config["waterfall_colors"]
     else:
         # fallback: black and white
         colors = [0x000000, 0xffffff]
     super().__init__(colors)
示例#19
0
 def getSharedInstance():
     with PskReporter.creationLock:
         if PskReporter.sharedInstance is None:
             if Config.get()["pskreporter_enabled"]:
                 PskReporter.sharedInstance = PskReporter()
             else:
                 PskReporter.sharedInstance = PskReporterDummy()
     return PskReporter.sharedInstance
示例#20
0
文件: audio.py 项目: jwt27/openwebrx
 def getSharedInstance():
     with DecoderQueue.creationLock:
         if DecoderQueue.sharedInstance is None:
             pm = Config.get()
             DecoderQueue.sharedInstance = DecoderQueue(
                 maxsize=pm["decoding_queue_length"],
                 workers=pm["decoding_queue_workers"])
     return DecoderQueue.sharedInstance
示例#21
0
    def removeOldPositions(self):
        pm = Config.get()
        retention = timedelta(seconds=pm["map_position_retention_time"])
        cutoff = datetime.now() - retention

        to_be_removed = [callsign for (callsign, pos) in self.positions.items() if pos["updated"] < cutoff]
        for callsign in to_be_removed:
            self.removeLocation(callsign)
示例#22
0
 def template_variables(self):
     settingslink = ""
     pm = Config.get()
     if "webadmin_enabled" in pm and pm["webadmin_enabled"]:
         settingslink = """<a class="button" href="settings" target="openwebrx-settings"><img src="static/gfx/openwebrx-panel-settings.png" alt="Settings"/><br/>Settings</a>"""
     header = self.render_template("include/header.include.html",
                                   settingslink=settingslink)
     return {"header": header}
示例#23
0
 def command_is_runnable(self, command):
     tmp_dir = Config.get()["temporary_directory"]
     cmd = shlex.split(command)
     try:
         process = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, cwd=tmp_dir)
         return process.wait() != 32512
     except FileNotFoundError:
         return False
示例#24
0
文件: sdr.py 项目: jketterl/openwebrx
 def store(self):
     # need to overwrite the existing key in the config since the layering won't capture the changes otherwise
     config = Config.get()
     sdrs = config["sdrs"]
     # a uuid should be unique, so i'm not sure if there's a point in this check
     if self.device_id in sdrs:
         raise ValueError("device {} already exists!".format(self.device_id))
     sdrs[self.device_id] = self.data_layer
     config["sdrs"] = sdrs
     super().store()
示例#25
0
 def __init__(self):
     super().__init__(
         Config.get(),
         "receiver_name",
         "receiver_location",
         "receiver_asl",
         "receiver_gps",
         "photo_title",
         "photo_desc",
     )
示例#26
0
文件: sdr.py 项目: jketterl/openwebrx
 def deleteDevice(self):
     if self.device_id is None:
         return self.send_response("device not found", code=404)
     config = Config.get()
     sdrs = config["sdrs"]
     del sdrs[self.device_id]
     # need to overwrite the existing key in the config since the layering won't capture the changes otherwise
     config["sdrs"] = sdrs
     config.store()
     return self.send_redirect("{}settings/sdr".format(self.get_document_root()))
示例#27
0
文件: wsjt.py 项目: jwt27/openwebrx
 def decoding_depth(self, mode):
     pm = Config.get()
     # mode-specific setting?
     if "wsjt_decoding_depths" in pm and mode in pm["wsjt_decoding_depths"]:
         return pm["wsjt_decoding_depths"][mode]
     # return global default
     if "wsjt_decoding_depth" in pm:
         return pm["wsjt_decoding_depth"]
     # default when no setting is provided
     return 3
示例#28
0
 def __init__(self, dsp, source, profile: AudioChopperProfile):
     self.dsp = dsp
     self.source = source
     self.profile = profile
     self.tmp_dir = Config.get()["temporary_directory"]
     self.wavefile = None
     self.wavefilename = None
     self.switchingLock = threading.Lock()
     self.timer = None
     (self.outputReader, self.outputWriter) = Pipe()
示例#29
0
 def handle_request(self):
     config = Config.get()
     if "webadmin_enabled" not in config or not config["webadmin_enabled"]:
         self.send_response("Web Admin is disabled", code=403)
         return
     if self.authentication.isAuthenticated(self.request):
         super().handle_request()
     else:
         target = "/login?{0}".format(
             parse.urlencode({"ref": self.request.path}))
         self.send_redirect(target)
示例#30
0
 def findKey(challenge):
     def parseKey(keyString):
         try:
             return Key(keyString)
         except KeyException as e:
             logger.error(e)
     keys = [parseKey(keyString) for keyString in Config.get()['receiver_keys']]
     keys = [key for key in keys if key is not None]
     matching_keys = [key for key in keys if key.source == challenge.source and key.id == challenge.id]
     if matching_keys:
         return matching_keys[0]
     return None