Source code for sitchlib.gsm_decomposer

"""Decompose GSM scans."""

from utility import Utility


[docs]class GsmDecomposer(object): """Decomposes GSM scans."""
[docs] @classmethod def decompose(cls, scan_document): """Turn one scan document into a list of channel scan documents. Args: scan_document (dict): GSM modem scan. Returns: list: List of tuples. First position in tuple identifies scan type. Second position is the actual scan data. """ results_set = [("cell", scan_document)] scan_items = scan_document["scan_results"] for channel in scan_items: try: channel = GsmDecomposer.enrich_channel_with_scan(channel, scan_document) channel["arfcn_int"] = GsmDecomposer.arfcn_int(channel["arfcn"]) # NOQA if channel["arfcn_int"] == 0 and channel["cell"] != "0": continue # If the data is incomplete, we don't forward # Now we bring the hex values to decimal... channel = GsmDecomposer.convert_hex_targets(channel) channel = GsmDecomposer.convert_float_targets(channel) # Setting CGI identifiers channel["cgi_str"] = GsmDecomposer.make_bts_friendly(channel) channel["cgi_int"] = GsmDecomposer.get_cgi_int(channel) chan_enriched = ('gsm_modem_channel', channel) results_set.append(chan_enriched) except Exception as e: print("Exception caught in GsmDecomposer: %s for channel %s in %s" % (e, str(channel), str(scan_document))) # NOQA return results_set
[docs] @classmethod def enrich_channel_with_scan(cls, channel, scan_document): """Enrich channel with scan document metadata.""" channel["band"] = scan_document["band"] channel["scan_finish"] = scan_document["scan_finish"] channel["site_name"] = scan_document["site_name"] channel["scan_location"] = scan_document["scan_location"] channel["scanner_public_ip"] = scan_document["scanner_public_ip"] return channel
[docs] @classmethod def arfcn_int(cls, arfcn): """Attempt to derive an integer representation of ARFCN.""" if arfcn == "65535": # This seems to be a default ARFCN on some modems return 0 try: arfcn_int = int(arfcn) except: msg = "GsmDecomposer: Unable to convert ARFCN to int" print(msg) print(arfcn) arfcn_int = 0 return arfcn_int
[docs] @classmethod def get_cgi_int(cls, channel): """Attempt to create an integer representation of CGI.""" try: cgi_int = int(channel["cgi_str"].replace(':', '')) except: print("EnrichGSM: Unable to convert CGI to int") print(channel["cgi_str"]) cgi_int = 0 return cgi_int
[docs] @classmethod def bts_from_channel(cls, channel): """Return clean BTS from channel.""" bts = {"mcc": channel["mcc"], "mnc": channel["mnc"], "lac": channel["lac"], "cellid": channel["cellid"]} return bts
[docs] @classmethod def make_bts_friendly(cls, bts_struct): """Expect a dict with keys for mcc, mnc, lac, cellid.""" retval = "%s:%s:%s:%s" % (str(bts_struct["mcc"]), str(bts_struct["mnc"]), str(bts_struct["lac"]), str(bts_struct["cellid"])) return retval
[docs] @classmethod def convert_hex_targets(cls, channel): """Convert LAC anc CellID from hex to decimal.""" for target in ['lac', 'cellid']: if target in channel: channel[target] = Utility.hex_to_dec(channel[target]) return channel
[docs] @classmethod def convert_float_targets(cls, channel): """Convert rxq and rxl to float.""" for target in ['rxq', 'rxl']: if target in channel: channel[target] = Utility.str_to_float(channel[target]) return channel