Ejemplo n.º 1
0
def write_mpad_repeater_data_to_disc(
    mpad_repeatermap_json: str,
    mpad_repeatermap_filename: str = "mpad_repeater_data.json",
):
    """
    writes the processed repeatermap data in enriched MPAD format
    to disc and returns the operation's status

    Parameters
    ==========
    mpad_repeatermap_json: 'str'
        json string which contains the enriched repeatermap data
    mpad_repeatermap_filename: 'str'
        file name of the native MPAD repeatermap data

    Returns
    =======
    success: 'bool'
        True if operation was successful
    """
    success = False
    absolute_path_filename = build_full_pathname(
        file_name=mpad_repeatermap_filename)
    try:
        with open(f"{absolute_path_filename}", "w") as f:
            f.write(mpad_repeatermap_json)
            f.close()
        success = True
    except:
        logger.info(
            msg=
            f"Cannot write native repeatermap data to local disc file '{absolute_path_filename}'"
        )
    return success
def update_local_airport_stations_file(
    airport_stations_filename: str = "airport_stations.txt", ):
    """
    Imports the ICAO/IATA data from the web and saves it to a local file.

    Parameters
    ==========
    airport_stations_filename : 'str'
        This local file will hold the content
        from https://www.aviationweather.gov/docs/metar/stations.txt.
        Default filename is "airport_stations.txt"

    Returns
    =======
    success: 'bool'
        True if operation was successful
    """

    # This is the fixed name of the URL Source that we are going to download
    file_url = "https://www.aviationweather.gov/docs/metar/stations.txt"
    success: bool = False

    absolute_path_filename = build_full_pathname(
        file_name=airport_stations_filename)

    # try to get the file
    try:
        r = requests.get(file_url)
    except:
        logger.info(msg=f"Cannot download airport data from '{file_url}'")
        r = None
    if r:
        if r.status_code == 200:
            try:
                with open(absolute_path_filename, "wb") as f:
                    f.write(r.content)
                    f.close()
                    success = True
            except:
                logger.info(
                    msg=
                    f"Cannot update airport data to local file '{absolute_path_filename}'"
                )
    return success
Ejemplo n.º 3
0
def read_mpad_satellite_data_from_disc(
    mpad_satellite_filename: str = "mpad_satellite_data.json", ):
    """
    reads the pre-processed satellite data in enriched MPAD format
    (JSON) from disc, then returns the operation's status
    and a dict object which contains the JSON data
    Enriched format contains TLE data plus frequencies

    Parameters
    ==========
    mpad_satellite_filename: 'str'
        file name of the native MPAD satellite data

    Returns
    =======
    success: 'bool'
        True if operation was successful
    mpad_satellite_data: 'dict'
        dictionary, containing the enriched satellite data
    """
    success = False
    absolute_path_filename = build_full_pathname(
        file_name=mpad_satellite_filename)
    mpad_satellite_data = {}  # create empty dict
    if check_if_file_exists(absolute_path_filename):
        try:
            with open(f"{absolute_path_filename}", "r") as f:
                if f.mode == "r":
                    mpad_satellite_data_json = f.read()
                    f.close()
                    mpad_satellite_data = json.loads(mpad_satellite_data_json)
                    success = True
        except:
            logger.info(
                msg=
                f"Cannot read MPAD satellite data file '{absolute_path_filename}' from disc"
            )
            success = False
    else:
        logger.info(
            msg=
            f"MPAD satellite data file '{absolute_path_filename}' does not exist"
        )
    return success, mpad_satellite_data
Ejemplo n.º 4
0
def read_mpad_repeatermap_data_from_disc(
    mpad_repeatermap_filename: str = "mpad_repeater_data.json", ):
    """
    Read the MPAD preprocessed repeatermap file from disc
    and return the JSON string if the file was found

    Parameters
    ==========
    mpad_repeatermap_filename: 'str'
        file name of the MPAD-enriched repeatermap data

    Returns
    =======
    success: 'bool'
        True if operation was successful
    mpad_repeatermap: 'dict'
        dictionary which contains the preprocessed repeatermap data
        (or empty dictionary if nothing was found)
    """
    success = False
    absolute_path_filename = build_full_pathname(
        file_name=mpad_repeatermap_filename)
    mpad_repeatermap = {}  # create empty dict
    if check_if_file_exists(absolute_path_filename):
        try:
            with open(f"{absolute_path_filename}", "r") as f:
                if f.mode == "r":
                    mpad_repeatermap_json = f.read()
                    f.close()
                    mpad_repeatermap = json.loads(mpad_repeatermap_json)
                    success = True
        except:
            logger.info(
                msg=
                f"Cannot read MPAD repeatermap data file '{absolute_path_filename}' from disc"
            )
            success = False
    else:
        logger.info(
            msg=
            f"MPAD repeatermap data file '{absolute_path_filename}' does not exist!"
        )
    return success, mpad_repeatermap
Ejemplo n.º 5
0
def download_and_write_local_satfreq_file(
    satfreq_filename: str = "satellite_frequencies.csv", ):
    """
    Download the amateur radio satellite frequency data
    and save it to a local file.

    Parameters
    ==========
    satfreq_filename : 'str'
        This local CSV file will hold the content
        from http://www.ne.jp/asahi/hamradio/je9pel/satslist.csv
        Default name is "satellite_frequencies.csv"

    Returns
    =======
    success: 'bool'
        True if operation was successful
    """

    file_url = "http://www.ne.jp/asahi/hamradio/je9pel/satslist.csv"
    success = False
    absolute_path_filename = build_full_pathname(file_name=satfreq_filename)

    try:
        r = requests.get(file_url)
    except:
        logger.info(
            msg=f"Cannot download satellite frequency data from {file_url}")
        r = None
    if r:
        if r.status_code == 200:
            try:
                with open(absolute_path_filename, "wb") as f:
                    f.write(r.content)
                    f.close()
                    success = True
            except:
                logger.info(
                    msg=
                    f"Cannot write satellite frequency csv file {absolute_path_filename} to disc"
                )
    return success
Ejemplo n.º 6
0
def download_and_write_local_tle_file(
        tle_filename: str = "tle_amateur_satellites.txt"):
    """
    Download the amateur radio satellite TLE data
    and save it to a local file.

    Parameters
    ==========
    tle_filename : 'str'
        This local file will hold the content
        from http://www.celestrak.com/NORAD/elements/amateur.txt
        Default is "tle_amateur_satellites.txt"

    Returns
    =======
    success: 'bool'
        True if operation was successful
    """

    # This is the fixed name of the file that we are going to download
    tle_data_file_url = "http://www.celestrak.com/NORAD/elements/amateur.txt"
    absolute_path_filename = build_full_pathname(file_name=tle_filename)
    success: bool = False

    # try to get the file
    try:
        r = requests.get(tle_data_file_url)
    except:
        logger.info(msg=f"Cannot download TLE data from {tle_data_file_url}")
        r = None
    if r:
        if r.status_code == 200:
            try:
                with open(absolute_path_filename, "wb") as f:
                    f.write(r.content)
                    f.close()
                    success = True
            except:
                logger.info(
                    msg=
                    f"Cannot update TLE data to file {absolute_path_filename}")
    return success
Ejemplo n.º 7
0
def read_hearham_raw_data_from_disk(
    hearham_raw_data_file: str = "hearham_raw_data.json", ):
    """
    Read the repeatermap.de raw data from disc.
    Return the file's content to the user as a JSON string for further processing

    Parameters
    ==========
    hearham_raw_data_file: 'str'
        Filename of the file which contains the raw data from hearham.de

    Returns
    =======
    success: 'bool'
        True if operation was successful
    repeatermap_raw_json_content: 'str'
        Contains the file's raw JSON content (otherwise 'None')
    """
    success = False
    hearham_raw_json_content = None
    absolute_path_filename = build_full_pathname(
        file_name=hearham_raw_data_file)
    if check_if_file_exists(absolute_path_filename):
        try:
            with open(f"{absolute_path_filename}", "r") as f:
                if f.mode == "r":
                    hearham_raw_json_content = f.read()
                    f.close()
                    success = True
        except:
            logger.info(
                msg=f"Cannot read '{absolute_path_filename}' from disc")
    else:
        logger.info(
            msg=
            f"Hearham.com raw data file '{absolute_path_filename}' does not exist!"
        )
    return success, hearham_raw_json_content
Ejemplo n.º 8
0
def download_hearham_raw_data_to_local_file(
    url: str = "https://hearham.com/api/repeaters/v1",
    hearham_raw_data_file: str = "hearham_raw_data.json",
):
    """
    Downloads the repeatermap.de data and write it to a file 'as is'
    That file needs to be post-processed at a later point in time

    Parameters
    ==========
    url: 'str'
        Source URL where we will get the data from.
    hearham_raw_data_file: 'str'
        Filename of the target file which will hold the raw data

    Returns
    =======
    success: 'bool'
        True if operation was successful
    """
    success = False
    absolute_path_filename = build_full_pathname(
        file_name=hearham_raw_data_file)
    resp = requests.get(url)
    if resp.status_code == 200:
        try:
            with open(f"{absolute_path_filename}", "w") as f:
                f.write(resp.text)
                f.close()
            success = True
        except:
            logger.info(
                msg=
                f"Cannot write hearham.com data to local disc file '{absolute_path_filename}'"
            )
    return success
def read_local_airport_data_file(
    airport_stations_filename: str = "airport_stations.txt", ):
    """
    Imports the ICAO/IATA data from a local file. Creates dictionaries for
    IATA-ICAO mapping and IATA-lat/lon mapping

    Parameters
    ==========
    airport_stations_filename : 'str'
        local file that is to be parsed. File format:
        see https://www.aviationweather.gov/docs/metar/stations.txt
        default filename: "airport_stations.txt"

    Returns
    =======
    iata_dict: 'dict'
        dictionary mapping between ICAO-Code (3 chars) and IATA-Code
        (4 chars) for all cases where such a mapping exists
    icao_dict: 'dict'
        Dictionary. References IATA-Code (4 chars) to lat/lon,
        METAR capability and the actual airport name
    """

    icao_dict = {}  # create empty dict
    iata_dict = {}  # create empty dict

    absolute_path_filename = build_full_pathname(
        file_name=airport_stations_filename)
    lines = None

    # Open the local file and read it
    if check_if_file_exists(absolute_path_filename):
        try:
            with open(f"{absolute_path_filename}", "r") as f:
                if f.mode == "r":
                    lines = f.readlines()
                    f.close()
        except:
            lines = None
    else:
        logger.info(
            msg=f"Airport data file '{absolute_path_filename}' does not exist")

    # If the file did contain content, then parse it
    if lines:
        # Start to parse the file content. The data that we want to digest
        # comes in lines of at least 63 chars and does not start with an
        # exclamation mark. Apart from that, everything is fixed file format

        for line in lines:
            line = line.rstrip()
            if len(line) > 63:
                if line[0] != "!" and line[0:11] != "CD  STATION":
                    # Extract all fields
                    icao = line[20:24]
                    icao = icao.strip()
                    iata = line[26:29]
                    iata = iata.strip()
                    latdeg = line[39:41]
                    latmin = line[42:44]
                    latns = line[44:45]
                    londeg = line[47:50]
                    lonmin = line[51:53]
                    lonns = line[53:54]
                    airport_name = line[3:19]
                    metar = line[62:63]

                    # set to 'METAR capable if content is present
                    if metar in ["X", "Z"]:
                        metar = True
                    else:
                        metar = False

                    # Convert DMS coordinates latitude
                    latitude = int(latdeg) + int(latmin) * (1 / 60)
                    if latns == "S":
                        latitude = latitude * -1

                    # Convert DMS coordinates latitude
                    longitude = int(londeg) + int(lonmin) * (1 / 60)
                    if lonns == "W":
                        longitude = longitude * -1

                    # Create IATA - ICAO relationship in dictionary
                    # if ICAO entry exists
                    if len(iata) != 0:
                        iata_dict[f"{iata}"] = {"icao": f"{icao}"}

                    # Create an entry for the IATA data
                    if len(icao) != 0:
                        icao_dict[f"{icao}"] = {
                            "latitude": latitude,
                            "longitude": longitude,
                            "metar_capable": metar,
                            "airport_name": airport_name,
                        }

    return iata_dict, icao_dict
Ejemplo n.º 10
0
def read_local_satfreq_file(
        satfreq_filename: str = "satellite_frequencies.csv"):
    """
    Reads the local amateur radio satellite frequency data
    from disc, transforms the data and creates a dictionary
    out of it.

    Parameters
    ==========
    satfreq_filename : 'str'
        This local CSV file holds the content
        from http://www.ne.jp/asahi/hamradio/je9pel/satslist.csv
        Default name is "satellite_frequencies.csv"

    Returns
    =======
    success: 'bool'
        True if operation was successful
    satellite_dictionary: 'dict'
        satellite dictionary, containing all satellites that
        we have found data for. Each satellite can have 1..n
        entries. Each entry can have different data fields.
        Primary key = satellite ID (not satellite name)
    """
    success = False
    absolute_path_filename = build_full_pathname(file_name=satfreq_filename)
    satellite_dictionary = {}

    if check_if_file_exists(absolute_path_filename):
        try:
            with open(absolute_path_filename) as csvfile:
                csv_object = csv.reader(csvfile, delimiter=";")
                for row in csv_object:
                    # Some rows from the CSV cannot be imported; we skip those
                    if len(row) > 6:
                        satellite_name = row[0].strip()
                        # Find the satellite NAME (contained in the brackets). If
                        # found, remove it from the string. Remainder is the
                        # satellit ID. This solution works for the majority
                        # of the entries in the list
                        regex_string = r"(\()(.*)(\))$"
                        matches = re.findall(
                            pattern=regex_string,
                            string=satellite_name,
                            flags=re.IGNORECASE,
                        )
                        if matches:
                            # This solution is far from ideal but the source file has way too many different formats
                            # so we'll try to get at least some of that data
                            satellite_key = re.sub(
                                pattern=regex_string,
                                repl="",
                                string=satellite_name,
                                flags=re.IGNORECASE,
                            ).strip()
                        else:
                            # if brackets are missing, assime satellite ID = satellite name
                            satellite_key = satellite_name.replace(" ", "-")

                        # Convert to UpperCase. This file may provide some
                        # sats in upper/lowercase; TLE data however is always in uppercase
                        satellite_key = satellite_key.upper()

                        # extract uplink/downloing frequencies etc
                        # do not convert to float but treat them as
                        # string; some entries contain more than one
                        # frequency value for e.g. uplink
                        uplink = row[2].strip()
                        uplink = uplink if len(uplink) != 0 else None
                        downlink = row[3].strip()
                        downlink = downlink if len(downlink) != 0 else None
                        beacon = row[4].strip()
                        beacon = beacon if len(beacon) != 0 else None
                        satellite_mode = row[5].strip()
                        satellite_mode = (satellite_mode if
                                          len(satellite_mode) != 0 else None)

                        # Create a dictionary entry for that single uplink/downlink entry
                        # Each satellite can have 1..n of such entries
                        satellite_element = {
                            # "satellite_name": satellite_name,
                            "uplink": uplink,
                            "downlink": downlink,
                            "beacon": beacon,
                            "satellite_mode": satellite_mode,
                        }
                        # We store these entries in a list
                        # if our satellite already exists in the final
                        # dictionary, get the existing list so we can
                        # add the new entry to it. Otherwise, create a
                        # new empty list.
                        # Finally, add the new entry
                        if satellite_key in satellite_dictionary:
                            satellite_data = satellite_dictionary[
                                satellite_key]
                        else:
                            satellite_data = []
                        satellite_data.append(satellite_element)
                        satellite_dictionary[satellite_key] = satellite_data
            success = True
        except:
            success = False
    else:
        logger.info(
            msg=
            f"Satellite frequency data file '{absolute_path_filename}' does not exist"
        )
    return success, satellite_dictionary
Ejemplo n.º 11
0
def read_local_tle_file(tle_filename: str = "tle_amateur_satellites.txt"):
    """
    Imports the Celestrak TLE data from a local file.
    Create dictionary based on given data.
    TLE data consists of three lines:
    Line 1 - identifier (aka satellite name)
    Line 2 - TLE Data Line 1
    Line 3 - TLE Data Line 2

    The identifier will be provided in two different formats:

    satellite name (satellite ID)
    OR
    satellite name

    If the satellite ID is present, this function will prefer the satellite ID
    over the satellite name.
    If only the satellite name (but no ID) is present, then all space characters
    will be replaced with dashes.

    Parameters
    ==========
    tle_filename : 'str'
        local file that is to be parsed. File format:
        see http://www.celestrak.com/NORAD/elements/amateur.txt

    Returns
    =======
    success: 'bool'
        True if operation was successful
    tle_data: 'dict'
        dictionary which contains the parsed data
    """

    success: bool = False
    tle_data = {}
    absolute_path_filename = build_full_pathname(file_name=tle_filename)
    lines = None

    # Open the local file and read it

    if check_if_file_exists(absolute_path_filename):
        try:
            with open(f"{absolute_path_filename}", "r") as f:
                if f.mode == "r":
                    lines = f.readlines()
                    f.close()
        except:
            lines = None
    else:
        logger.info(
            msg=f"Celestrak TLE file '{absolute_path_filename}' does not exist"
        )

    if lines:
        if len(lines) % 3 != 0:
            logger.info(
                msg=f"Invalid TLE file structure for file {tle_filename}")
            success = False
            return success, tle_data
        lc = 1
        # Retrieve the data and create the dictionary
        for tle_satellite in lines[0::3]:

            # Process the key. Try to extract the ID (if present).
            # Otherwise, replace all blanks with dashes
            tle_satellite = tle_satellite.rstrip()
            matches = re.search(r"^.*(\()(.*)(\))$", tle_satellite)
            if matches:
                tle_key = matches[2]
            else:
                tle_key = tle_satellite.replace(" ", "-")
            # Ensure that the key is always in uppercase
            tle_key = tle_key.upper()

            # Convenience mapping :-)
            if tle_key == "ZARYA":
                tle_key = "ISS"

            # Get the actual TLE data
            tle_line1 = lines[lc].rstrip()
            tle_line2 = lines[lc + 1].rstrip()
            lc += 3
            tle_data[f"{tle_key}"] = {
                "satellite_name": tle_satellite,
                "tle_line1": tle_line1,
                "tle_line2": tle_line2,
            }
    # Did we manage to download something?
    success: bool = True if len(tle_data) != 0 else False
    return success, tle_data