Ejemplo n.º 1
0
 def _debug_msg(self, msg):
     df = pms.df(msg)
     msglen = len(msg)
     if df == 17 and msglen == 28:
         print(msg, pms.icao(msg), pms.crc(msg))
     elif df in [20, 21] and msglen == 28:
         print(msg, pms.icao(msg))
     elif df in [4, 5, 11] and msglen == 14:
         print(msg, pms.icao(msg))
     else:
         # print("[*]", msg)
         pass
Ejemplo n.º 2
0
def streamFromZMQ(addr, topic=""):
    context = zmq.Context()

    log.info(f"Setting up ZMQ SUB socket connecting to {addr}")
    insocket = context.socket(zmq.SUB)
    insocket.connect(addr)

    log.info(f"Subscribing to ZMQ topic \"{topic}\"")
    insocket.subscribe(topic)

    while True:
        if insocket.poll(10) != 0:  # check if there is a message on the socket
            (_, meta, _) = insocket.recv_multipart()
            log.debug(meta)

            jmeta = json.loads(meta.decode("utf-8"))
            msg = jmeta["decode.msg"]

            icao = pms.icao(msg)
            verif_status = jmeta[
                "verify.status"] if "verify.status" in jmeta else "None"
            tc = pms.adsb.typecode(msg)
            (lat, lon) = (
                None,
                None) if tc < 9 or tc > 18 else pms.adsb.position_with_ref(
                    msg, LAT, LON)

            if (lat, lon) == (None, None):
                continue

            #convert to webmercator
            x, y = tra.transform(lon, lat)

            newdetails = (lat, lon, x, y, icao, verif_status, time.time())

            for q in qs:
                try:
                    q.put(newdetails, block=False)
                except queue.Full:
                    log.warning("Full queue, discarding oldest update")
                    q.get(block=False)
                    q.put(newdetails, block=False
                          )  #TODO: this could just throw an error again

        else:
            time.sleep(0.5)  # wait 500ms and try again
            continue
Ejemplo n.º 3
0
    def process_raw(self, adsb_ts, adsb_msg, commb_ts, commb_msg, tnow=None):
        """process a chunk of adsb and commb messages recieved in the same
        time period.
        """
        if tnow is None:
            tnow = time.time()

        self.t = tnow

        local_updated_acs_buffer = []
        output_buffer = []

        # process adsb message
        for t, msg in zip(adsb_ts, adsb_msg):
            icao = pms.icao(msg)
            tc = pms.adsb.typecode(msg)

            if icao not in self.acs:
                self.acs[icao] = {
                    "live": None,
                    "call": None,
                    "lat": None,
                    "lon": None,
                    "alt": None,
                    "gs": None,
                    "trk": None,
                    "roc": None,
                    "tas": None,
                    "roll": None,
                    "rtrk": None,
                    "ias": None,
                    "mach": None,
                    "hdg": None,
                    "ver": None,
                    "HPL": None,
                    "RCu": None,
                    "RCv": None,
                    "HVE": None,
                    "VVE": None,
                    "Rc": None,
                    "VPL": None,
                    "EPU": None,
                    "VEPU": None,
                    "HFOMr": None,
                    "VFOMr": None,
                    "PE_RCu": None,
                    "PE_VPL": None,
                }

            self.acs[icao]["t"] = t
            self.acs[icao]["live"] = int(t)

            if 1 <= tc <= 4:
                cs = pms.adsb.callsign(msg)
                self.acs[icao]["call"] = cs
                output_buffer.append([t, icao, "cs", cs])

            if (5 <= tc <= 8) or (tc == 19):
                vdata = pms.adsb.velocity(msg)
                if vdata is None:
                    continue

                spd, trk, roc, tag = vdata
                if tag != "GS":
                    continue
                if (spd is None) or (trk is None):
                    continue

                self.acs[icao]["gs"] = spd
                self.acs[icao]["trk"] = trk
                self.acs[icao]["roc"] = roc
                self.acs[icao]["tv"] = t

                output_buffer.append([t, icao, "gs", spd])
                output_buffer.append([t, icao, "trk", trk])
                output_buffer.append([t, icao, "roc", roc])

            if 5 <= tc <= 18:
                oe = pms.adsb.oe_flag(msg)
                self.acs[icao][oe] = msg
                self.acs[icao]["t" + str(oe)] = t

                if ("tpos" in self.acs[icao]) and (t - self.acs[icao]["tpos"] <
                                                   180):
                    # use single message decoding
                    rlat = self.acs[icao]["lat"]
                    rlon = self.acs[icao]["lon"]
                    latlon = pms.adsb.position_with_ref(msg, rlat, rlon)
                elif (("t0" in self.acs[icao]) and ("t1" in self.acs[icao]) and
                      (abs(self.acs[icao]["t0"] - self.acs[icao]["t1"]) < 10)):
                    # use multi message decoding
                    try:
                        latlon = pms.adsb.position(
                            self.acs[icao][0],
                            self.acs[icao][1],
                            self.acs[icao]["t0"],
                            self.acs[icao]["t1"],
                            self.lat0,
                            self.lon0,
                        )
                    except:
                        # mix of surface and airborne position message
                        continue
                else:
                    latlon = None

                if latlon is not None:
                    self.acs[icao]["tpos"] = t
                    self.acs[icao]["lat"] = latlon[0]
                    self.acs[icao]["lon"] = latlon[1]

                    alt = pms.adsb.altitude(msg)
                    self.acs[icao]["alt"] = alt

                    output_buffer.append([t, icao, "lat", latlon[0]])
                    output_buffer.append([t, icao, "lon", latlon[1]])
                    output_buffer.append([t, icao, "alt", alt])

                    local_updated_acs_buffer.append(icao)

            # Uncertainty & accuracy
            ac = self.acs[icao]

            if 9 <= tc <= 18:
                ac["nic_bc"] = pms.adsb.nic_b(msg)

            if (5 <= tc <= 8) or (9 <= tc <= 18) or (20 <= tc <= 22):
                ac["HPL"], ac["RCu"], ac["RCv"] = pms.adsb.nuc_p(msg)

                if (ac["ver"] == 1) and ("nic_s" in ac.keys()):
                    ac["Rc"], ac["VPL"] = pms.adsb.nic_v1(msg, ac["nic_s"])
                elif ((ac["ver"] == 2) and ("nic_a" in ac.keys())
                      and ("nic_bc" in ac.keys())):
                    ac["Rc"] = pms.adsb.nic_v2(msg, ac["nic_a"], ac["nic_bc"])

            if tc == 19:
                ac["HVE"], ac["VVE"] = pms.adsb.nuc_v(msg)
                if ac["ver"] in [1, 2]:
                    ac["HFOMr"], ac["VFOMr"] = pms.adsb.nac_v(msg)

            if tc == 29:
                ac["PE_RCu"], ac["PE_VPL"], ac["base"] = pms.adsb.sil(
                    msg, ac["ver"])
                ac["EPU"], ac["VEPU"] = pms.adsb.nac_p(msg)

            if tc == 31:
                ac["ver"] = pms.adsb.version(msg)
                ac["EPU"], ac["VEPU"] = pms.adsb.nac_p(msg)
                ac["PE_RCu"], ac["PE_VPL"], ac["sil_base"] = pms.adsb.sil(
                    msg, ac["ver"])

                if ac["ver"] == 1:
                    ac["nic_s"] = pms.adsb.nic_s(msg)
                elif ac["ver"] == 2:
                    ac["nic_a"], ac["nic_bc"] = pms.adsb.nic_a_c(msg)

        # process commb message
        for t, msg in zip(commb_ts, commb_msg):
            icao = pms.icao(msg)

            if icao not in self.acs:
                continue

            self.acs[icao]["live"] = int(t)

            bds = pms.bds.infer(msg)

            if bds == "BDS50":
                roll50 = pms.commb.roll50(msg)
                trk50 = pms.commb.trk50(msg)
                rtrk50 = pms.commb.rtrk50(msg)
                gs50 = pms.commb.gs50(msg)
                tas50 = pms.commb.tas50(msg)

                self.acs[icao]["t50"] = t
                if tas50:
                    self.acs[icao]["tas"] = tas50
                    output_buffer.append([t, icao, "tas50", tas50])
                if roll50:
                    self.acs[icao]["roll"] = roll50
                    output_buffer.append([t, icao, "roll50", roll50])
                if rtrk50:
                    self.acs[icao]["rtrk"] = rtrk50
                    output_buffer.append([t, icao, "rtrk50", rtrk50])

                if trk50:
                    output_buffer.append([t, icao, "trk50", trk50])
                if gs50:
                    output_buffer.append([t, icao, "gs50", gs50])

            elif bds == "BDS60":
                ias60 = pms.commb.ias60(msg)
                hdg60 = pms.commb.hdg60(msg)
                mach60 = pms.commb.mach60(msg)
                roc60baro = pms.commb.vr60baro(msg)
                roc60ins = pms.commb.vr60ins(msg)

                if ias60 or hdg60 or mach60:
                    self.acs[icao]["t60"] = t
                if ias60:
                    self.acs[icao]["ias"] = ias60
                if hdg60:
                    self.acs[icao]["hdg"] = hdg60
                if mach60:
                    self.acs[icao]["mach"] = mach60

                if roc60baro:
                    output_buffer.append([t, icao, "roc60baro", roc60baro])
                if roc60ins:
                    output_buffer.append([t, icao, "roc60ins", roc60ins])

        # clear up old data
        for icao in list(self.acs.keys()):
            if self.t - self.acs[icao]["live"] > self.cache_timeout:
                del self.acs[icao]
                continue

        if self.dumpto is not None:
            dh = str(datetime.datetime.now().strftime("%Y%m%d_%H"))
            fn = self.dumpto + "/pymodes_dump_%s.csv" % dh
            output_buffer.sort(key=lambda x: x[0])
            with open(fn, "a") as f:
                writer = csv.writer(f)
                writer.writerows(output_buffer)

        return
Ejemplo n.º 4
0
    def process_raw(self, adsb_ts, adsb_msgs, commb_ts, commb_msgs, tnow=None):
        """process a chunk of adsb and commb messages recieved in the same
        time period.
        """
        if tnow is None:
            tnow = time.time()

        self.t = tnow

        local_updated_acs_buffer = []

        # process adsb message
        for t, msg in zip(adsb_ts, adsb_msgs):
            icao = pms.icao(msg)
            tc = pms.adsb.typecode(msg)

            if icao not in self.acs:
                self.acs[icao] = {
                    'live': None,
                    'call': None,
                    'lat': None,
                    'lon': None,
                    'alt': None,
                    'gs': None,
                    'trk': None,
                    'roc': None,
                    'tas': None,
                    'ias': None,
                    'mach': None,
                    'hdg': None,
                    'ver': None,
                    'HPL': None,
                    'RCu': None,
                    'RCv': None,
                    'HVE': None,
                    'VVE': None,
                    'Rc': None,
                    'VPL': None,
                    'EPU': None,
                    'VEPU': None,
                    'HFOMr': None,
                    'VFOMr': None,
                    'PE_RCu': None,
                    'PE_VPL': None,
                }

            self.acs[icao]['live'] = int(t)

            if 1 <= tc <= 4:
                self.acs[icao]['call'] = pms.adsb.callsign(msg)

            if (5 <= tc <= 8) or (tc == 19):
                vdata = pms.adsb.velocity(msg)
                if vdata is None:
                    continue

                spd, trk, roc, tag = vdata
                if tag != 'GS':
                    continue
                if (spd is None) or (trk is None):
                    continue

                self.acs[icao]['gs'] = spd
                self.acs[icao]['trk'] = trk
                self.acs[icao]['roc'] = roc
                self.acs[icao]['tv'] = t

            if (5 <= tc <= 18):
                oe = pms.adsb.oe_flag(msg)
                self.acs[icao][oe] = msg
                self.acs[icao]['t' + str(oe)] = t

                if ('tpos' in self.acs[icao]) and (t - self.acs[icao]['tpos'] <
                                                   180):
                    # use single message decoding
                    rlat = self.acs[icao]['lat']
                    rlon = self.acs[icao]['lon']
                    latlon = pms.adsb.position_with_ref(msg, rlat, rlon)
                elif ('t0' in self.acs[icao]) and ('t1' in self.acs[icao]) and \
                     (abs(self.acs[icao]['t0'] - self.acs[icao]['t1']) < 10):
                    # use multi message decoding
                    # try:
                    latlon = pms.adsb.position(self.acs[icao][0],
                                               self.acs[icao][1],
                                               self.acs[icao]['t0'],
                                               self.acs[icao]['t1'], self.lat0,
                                               self.lon0)
                    # except:
                    #     # mix of surface and airborne position message
                    #     continue
                else:
                    latlon = None

                if latlon is not None:
                    self.acs[icao]['tpos'] = t
                    self.acs[icao]['lat'] = latlon[0]
                    self.acs[icao]['lon'] = latlon[1]
                    self.acs[icao]['alt'] = pms.adsb.altitude(msg)
                    local_updated_acs_buffer.append(icao)

            # Uncertainty & accuracy
            ac = self.acs[icao]

            if 9 <= tc <= 18:
                ac['nic_bc'] = pms.adsb.nic_b(msg)

            if (5 <= tc <= 8) or (9 <= tc <= 18) or (20 <= tc <= 22):
                ac['HPL'], ac['RCu'], ac['RCv'] = pms.adsb.nuc_p(msg)

                if (ac['ver'] == 1) and ('nic_s' in ac.keys()):
                    ac['Rc'], ac['VPL'] = pms.adsb.nic_v1(msg, ac['nic_s'])
                elif (ac['ver'] == 2) and ('nic_a'
                                           in ac.keys()) and ('nic_bc'
                                                              in ac.keys()):
                    ac['Rc'] = pms.adsb.nic_v2(msg, ac['nic_a'], ac['nic_bc'])

            if tc == 19:
                ac['HVE'], ac['VVE'] = pms.adsb.nuc_v(msg)
                if ac['ver'] in [1, 2]:
                    ac['HFOMr'], ac['VFOMr'] = pms.adsb.nac_v(msg)

            if tc == 29:
                ac['PE_RCu'], ac['PE_VPL'], ac['base'] = pms.adsb.sil(
                    msg, ac['ver'])
                ac['EPU'], ac['VEPU'] = pms.adsb.nac_p(msg)

            if tc == 31:
                ac['ver'] = pms.adsb.version(msg)
                ac['EPU'], ac['VEPU'] = pms.adsb.nac_p(msg)
                ac['PE_RCu'], ac['PE_VPL'], ac['sil_base'] = pms.adsb.sil(
                    msg, ac['ver'])

                if ac['ver'] == 1:
                    ac['nic_s'] = pms.adsb.nic_s(msg)
                elif ac['ver'] == 2:
                    ac['nic_a'], ac['nic_bc'] = pms.adsb.nic_a_c(msg)

        # process commb message
        for t, msg in zip(commb_ts, commb_msgs):
            icao = pms.icao(msg)

            if icao not in self.acs:
                continue

            bds = pms.bds.infer(msg)

            if bds == 'BDS50':
                tas = pms.commb.tas50(msg)

                if tas:
                    self.acs[icao]['t50'] = t
                    self.acs[icao]['tas'] = tas

            elif bds == 'BDS60':
                ias = pms.commb.ias60(msg)
                hdg = pms.commb.hdg60(msg)
                mach = pms.commb.mach60(msg)

                if ias or hdg or mach:
                    self.acs[icao]['t60'] = t
                if ias:
                    self.acs[icao]['ias'] = ias
                if hdg:
                    self.acs[icao]['hdg'] = hdg
                if mach:
                    self.acs[icao]['mach'] = mach

        # clear up old data
        for icao in list(self.acs.keys()):
            if self.t - self.acs[icao]['live'] > self.cache_timeout:
                del self.acs[icao]
                continue

        if self.cache_new_acs:
            self.add_new_aircraft(local_updated_acs_buffer)

        return
Ejemplo n.º 5
0
    def process(
        self,
        time: datetime,
        msg: str,
        *args: Any,
        uncertainty: bool = False,
        spd: Optional[float] = None,
        trk: Optional[float] = None,
        alt: Optional[float] = None,
    ) -> None:

        ac: Aircraft

        if len(msg) != 28:
            return

        df = pms.df(msg)

        if df == 4 or df == 20:
            icao = pms.icao(msg)
            if isinstance(icao, bytes):
                icao = icao.decode()
            ac = self.acs[icao.lower()]
            ac.altcode = time, msg  # type: ignore

        if df == 5 or df == 21:
            icao = pms.icao(msg)
            if isinstance(icao, bytes):
                icao = icao.decode()
            ac = self.acs[icao.lower()]
            ac.idcode = time, msg  # type: ignore

        if df == 17 or df == 18:  # ADS-B

            if pms.crc(msg, encode=False) != 0:
                return

            tc = pms.adsb.typecode(msg)
            icao = pms.icao(msg)

            # before it's fixed in pyModeS release...
            if isinstance(icao, bytes):
                icao = icao.decode()

            ac = self.acs[icao.lower()]

            if 1 <= tc <= 4:
                ac.callsign = time, msg  # type: ignore

            if 5 <= tc <= 8:
                ac.surface = time, msg  # type: ignore

            if tc == 19:
                ac.speed = time, msg  # type: ignore

            if 9 <= tc <= 18:
                # This is barometric altitude
                ac.position = time, msg  # type: ignore

            if 20 <= tc <= 22:
                # Only GNSS altitude
                pass

            if not uncertainty:
                return

            if 9 <= tc <= 18:
                ac.nic_bc = pms.adsb.nic_b(msg)

            if (5 <= tc <= 8) or (9 <= tc <= 18) or (20 <= tc <= 22):
                ac.nuc_p = time, msg  # type: ignore
                if ac.version == 1:
                    ac.nic_v1 = time, msg  # type: ignore
                elif ac.version == 2:
                    ac.nic_v2 = time, msg  # type: ignore

            if tc == 19:
                ac.nuc_r = time, msg  # type: ignore
                if ac.version in [1, 2]:
                    ac.nac_v = time, msg  # type: ignore

            if tc == 29:
                ac.sil = time, msg  # type: ignore
                ac.nac_p = time, msg  # type: ignore

            if tc == 31:
                ac.version = pms.adsb.version(msg)
                ac.sil = time, msg  # type: ignore
                ac.nac_p = time, msg  # type: ignore

                if ac.version == 1:
                    ac.nic_s = pms.adsb.nic_s(msg)
                elif ac.version == 2:
                    ac.nic_a, ac.nic_bc = pms.adsb.nic_a_c(msg)

        elif df == 20 or df == 21:

            bds = pms.bds.infer(msg)
            icao = pms.icao(msg)
            if isinstance(icao, bytes):
                icao = icao.decode()
            ac = self.acs[icao.lower()]

            if bds == "BDS20":
                ac.bds20 = time, msg  # type: ignore
                return

            if bds == "BDS40":
                ac.bds40 = time, msg  # type: ignore
                return

            if bds == "BDS44":
                ac.bds44 = time, msg  # type: ignore
                return

            if bds == "BDS45":
                ac.bds45 = time, msg  # type: ignore
                return

            if bds == "BDS50,BDS60":
                if spd is not None and trk is not None and alt is not None:
                    bds = pms.bds.is50or60(msg, spd, trk, alt)
                elif (ac.spd is not None and ac.trk is not None
                      and ac.alt is not None):
                    bds = pms.bds.is50or60(msg, ac.spd, ac.trk, ac.alt)
                else:
                    return
                # do not return!

            if bds == "BDS50":
                ac.bds50 = time, msg  # type: ignore
                return

            if bds == "BDS60":
                ac.bds60 = time, msg  # type: ignore
                return
Ejemplo n.º 6
0
            continue

        jmeta = json.loads(meta)

        logging.debug((meta, len(data)))

        burst = np.frombuffer(data, dtype=np.complex64)
        if outf["inds"].shape[
                0] == bursti:  #TODO: resizing by one each time is probably horribly un-performant
            outf["inds"].resize(bursti + 1, axis=0)
            outf["outds"].resize(bursti + 1, axis=0)
            outf["meta_datahex"].resize(bursti + 1, axis=0)
            outf["meta_msgtime"].resize(bursti + 1, axis=0)
            outf["meta_storetime"].resize(bursti + 1, axis=0)
            outf["meta_uuid"].resize(bursti + 1, axis=0)
        outf["inds"][bursti, :, 0] = np.real(burst)
        outf["inds"][bursti, :, 1] = np.imag(burst)
        outf["outds"][bursti, :] = np.string_(pms.icao(jmeta["decode.msg"]))
        outf["meta_datahex"][bursti, :] = np.string_(jmeta["decode.msg"])
        outf["meta_msgtime"][bursti, :] = float(
            jmeta["msgtime"]) if "msgtime" in jmeta else -1.0
        outf["meta_storetime"][bursti, :] = time.time()
        outf["meta_uuid"][bursti, :] = np.string_(jmeta["uuid"])

        bursti += 1

        if bursti % 100 == 0:
            logging.info(f"Stored {bursti} bursts (with meta)")
finally:
    outf.close()
Ejemplo n.º 7
0
    def process_raw(self, adsb_ts, adsb_msgs, ehs_ts, ehs_msgs, tnow=None):
        """process a chunk of adsb and ehs messages received in the same
        time period.
        """
        if tnow is None:
            tnow = time.time()

        self.t = tnow

        local_ehs_updated_acs_buffer = []

        # process adsb message
        for t, msg in zip(adsb_ts, adsb_msgs):
            icao = pms.icao(msg)
            tc = pms.adsb.typecode(msg)

            if icao not in self.acs:
                self.acs[icao] = {}
                if self.correction:
                    try:
                        self.acs[icao]['magdev'] = acdb.loc[icao]['magdev']
                    except:  #no icao in database
                        self.acs[icao]['magdev'] = 0
                else:
                    self.acs[icao]['magdev'] = 0

            self.acs[icao]['t'] = t

            if 1 <= tc <= 4:
                self.acs[icao]['callsign'] = pms.adsb.callsign(msg)

            if (5 <= tc <= 8) or (tc == 19):
                vdata = pms.adsb.velocity(msg)
                if vdata is None:
                    continue

                spd, trk, roc, tag = vdata
                if tag != 'GS':
                    continue

                self.acs[icao]['gs'] = spd
                self.acs[icao]['trk'] = trk
                self.acs[icao]['roc'] = roc
                self.acs[icao]['tv'] = t

            if (5 <= tc <= 18):
                oe = pms.adsb.oe_flag(msg)
                self.acs[icao][oe] = msg
                self.acs[icao]['t' + str(oe)] = t

                if ('tpos' in self.acs[icao]) and (t - self.acs[icao]['tpos'] <
                                                   180):
                    # use single message decoding
                    rlat = self.acs[icao]['lat']
                    rlon = self.acs[icao]['lon']
                    latlon = pms.adsb.position_with_ref(msg, rlat, rlon)
                elif ('t0' in self.acs[icao]) and ('t1' in self.acs[icao]) and \
                     (abs(self.acs[icao]['t0'] - self.acs[icao]['t1']) < 10):
                    # use multi message decoding
                    try:
                        latlon = pms.adsb.position(self.acs[icao][0],
                                                   self.acs[icao][1],
                                                   self.acs[icao]['t0'],
                                                   self.acs[icao]['t1'],
                                                   self.lat0, self.lon0)
                    except:
                        # mix of surface and airborne position message
                        continue
                else:
                    latlon = None

                if latlon is not None:
                    self.acs[icao]['tpos'] = t
                    self.acs[icao]['lat'] = latlon[0]
                    self.acs[icao]['lon'] = latlon[1]
                    self.acs[icao]['alt'] = pms.adsb.altitude(msg)

        # process ehs message
        for t, msg in zip(ehs_ts, ehs_msgs):
            icao = pms.icao(msg)

            if icao not in self.acs:
                continue

            if self.correction:
                # Check DF20
                if pms.df(msg) == 20:
                    alt_ehs = pms.altcode(msg)

                    if ('alt' in self.acs[icao]) and (alt_ehs is not None):
                        if abs(self.acs[icao]['alt'] - alt_ehs) > 250:
                            continue
                    else:
                        # No ADS-B altitude yet, so no altitude comparision possible
                        continue

                # Check DF21
                if pms.df(msg) == 21:
                    squawk = pms.idcode(msg)

                    if squawk not in self.squawks:
                        self.squawks[squawk] = {}

                    if icao not in self.squawks[squawk]:
                        self.squawks[squawk][icao] = {}
                        self.squawks[squawk][icao]['count'] = 0

                    self.squawks[squawk][icao]['count'] += 1
                    self.squawks[squawk][icao]['ts'] = t

                    if self.squawks[squawk][icao]['count'] < 10:
                        # Reject if Squawk and ICAO combination has seen less than 10 times.
                        continue

            bds = pms.bds.infer(msg)

            if bds == 'BDS50,BDS60':
                try:
                    bds = pms.bds.is50or60(msg, self.acs[icao]['gs'],
                                           self.acs[icao]['trk'],
                                           self.acs[icao]['alt'])
                except:
                    pass

            if bds == 'BDS50':
                tas = pms.commb.tas50(msg)
                roll = pms.commb.roll50(msg)

                if tas and roll:
                    self.acs[icao]['t50'] = t
                    self.acs[icao]['tas'] = tas
                    self.acs[icao]['roll'] = roll
                    local_ehs_updated_acs_buffer.append(icao)

            elif bds == 'BDS60':
                ias = pms.commb.ias60(msg)
                hdg = pms.commb.hdg60(msg)
                mach = pms.commb.mach60(msg)

                if ias and hdg and mach:
                    self.acs[icao]['t60'] = t
                    self.acs[icao]['ias'] = ias
                    self.acs[icao]['hdg'] = hdg
                    self.acs[icao]['mach'] = mach
                    local_ehs_updated_acs_buffer.append(icao)

        # clear up old data
        for icao in list(self.acs.keys()):
            if self.t - self.acs[icao]['t'] > 180:
                del self.acs[icao]
                continue

            if ('t50' in self.acs[icao]) and (self.t - self.acs[icao]['t50'] >
                                              5):
                del self.acs[icao]['t50']
                del self.acs[icao]['tas']

            if ('t60' in self.acs[icao]) and (self.t - self.acs[icao]['t60'] >
                                              5):
                del self.acs[icao]['t60']
                del self.acs[icao]['ias']
                del self.acs[icao]['hdg']
                del self.acs[icao]['mach']

        self.add_ehs_updated_aircraft(local_ehs_updated_acs_buffer)

        if self.correction:
            for squawk in list(self.squawks):
                for icao in list(self.squawks[squawk]):
                    if self.t - self.squawks[squawk][icao]['ts'] > 300:
                        del self.squawks[squawk][icao]

    #                     print('deleted', squawk, icao)

        return
Ejemplo n.º 8
0
    def process(
        self,
        time: datetime,
        msg: bytes,
        *args,
        spd: Optional[float] = None,
        trk: Optional[float] = None,
        alt: Optional[float] = None,
    ) -> None:

        if len(msg) != 28:
            return

        df = pms.df(msg)

        if df == 4 or df == 20:
            icao = pms.icao(msg)
            ac = self.acs[icao.lower()]
            ac.altcode = time, msg

        if df == 5 or df == 21:
            icao = pms.icao(msg)
            ac = self.acs[icao.lower()]
            ac.idcode = time, msg

        if df == 17 or df == 18:  # ADS-B

            if pms.crc(msg, encode=False) != 0:
                return

            tc = pms.adsb.typecode(msg)
            icao = pms.icao(msg)
            ac = self.acs[icao.lower()]

            if 1 <= tc <= 4:
                ac.callsign = time, msg

            if 5 <= tc <= 8:
                ac.surface = time, msg

            if tc == 19:
                ac.speed = time, msg

            if 9 <= tc <= 18:
                # This is barometric altitude
                ac.position = time, msg

            if 20 <= tc <= 22:
                # Only GNSS altitude
                pass

            # if 9 <= tc <= 18:
            #     ac["nic_bc"] = pms.adsb.nic_b(msg)

            # if (5 <= tc <= 8) or (9 <= tc <= 18) or (20 <= tc <= 22):
            #     ac["HPL"], ac["RCu"], ac["RCv"] = pms.adsb.nuc_p(msg)

            #     if (ac["ver"] == 1) and ("nic_s" in ac.keys()):
            #         ac["Rc"], ac["VPL"] = pms.adsb.nic_v1(msg, ac["nic_s"])
            #     elif (
            #         (ac["ver"] == 2)
            #         and ("nic_a" in ac.keys())
            #         and ("nic_bc" in ac.keys())
            #     ):
            #         ac["Rc"] = pms.adsb.nic_v2(msg, ac["nic_a"], ac["nic_bc"])

            # if tc == 19:
            #     ac["HVE"], ac["VVE"] = pms.adsb.nuc_v(msg)
            #     if ac["ver"] in [1, 2]:
            #         ac["EPU"], ac["VEPU"] = pms.adsb.nac_v(msg)

            # if tc == 29:
            #     ac["PE_RCu"], ac["PE_VPL"], ac["base"] = pms.adsb.sil(
            #         msg, ac["ver"]
            #     )
            #     ac["HFOMr"], ac["VFOMr"] = pms.adsb.nac_p(msg)

            # if tc == 31:
            #     ac["ver"] = pms.adsb.version(msg)
            #     ac["HFOMr"], ac["VFOMr"] = pms.adsb.nac_p(msg)
            #     ac["PE_RCu"], ac["PE_VPL"], ac["sil_base"] = pms.adsb.sil(
            #         msg, ac["ver"]
            #     )

            #     if ac["ver"] == 1:
            #         ac["nic_s"] = pms.adsb.nic_s(msg)
            #     elif ac["ver"] == 2:
            #         ac["nic_a"], ac["nic_bc"] = pms.adsb.nic_a_c(msg)

        elif df == 20 or df == 21:

            bds = pms.bds.infer(msg)
            icao = pms.icao(msg)
            ac = self.acs[icao.lower()]

            if bds == "BDS20":
                ac.bds20 = time, msg
                return

            if bds == "BDS40":
                ac.bds40 = time, msg
                return

            if bds == "BDS44":
                ac.bds44 = time, msg
                return

            if bds == "BDS45":
                ac.bds45 = time, msg
                return

            if bds == "BDS50,BDS60":
                if spd is not None and trk is not None and alt is not None:
                    bds = pms.bds.is50or60(msg, spd, trk, alt)
                elif (ac.spd is not None and ac.trk is not None
                      and ac.alt is not None):
                    bds = pms.bds.is50or60(msg, ac.spd, ac.trk, ac.alt)
                else:
                    return
                # do not return!

            if bds == "BDS50":
                ac.bds50 = time, msg
                return

            if bds == "BDS60":
                ac.bds60 = time, msg
                return
    mtc = msgtype_counts[mt]
    mtcp = mtc / msgtype_total
    if mtcp > 0.1:
        print(
            "Type {}: count = {} / {} ({:.2f}%), success = {} / {} ({:.2f}%)".
            format(mt, mtc, msgtype_total, 100.0 * mtcp, mts, mtc,
                   100.0 * mts / mtc))

#create final output file with single dataset
h5int = h5py.File(interfilename, "r")
h5out = h5py.File(outfilename, "w")

#save for siamese script
h5out.create_dataset("inds", (h5int_i, 2400, 2), dtype=np.float32)
h5out.create_dataset("outds", (h5int_i, 1), dtype="S6")
h5out.create_dataset("meta_datahex", (h5int_i, 1),
                     dtype="S28")  #28 characters as each byte is 2 hex chars
for h5out_i in range(h5int_i):
    burst = h5int["bursts_" + str(h5out_i)]
    h5out["inds"][h5out_i, :, 0] = np.real(burst)
    h5out["inds"][h5out_i, :, 1] = np.imag(burst)
    h5out["outds"][h5out_i, :] = np.string_(
        pms.icao(h5int["bursts_" + str(h5out_i)].attrs["libmodes_datahex"]))
    h5out["meta_datahex"][h5out_i, :] = np.string_(
        h5int["bursts_" + str(h5out_i)].attrs["libmodes_datahex"])
h5out.close()
h5int.close()

#delete the intermediate file
os.remove(interfilename)
Ejemplo n.º 10
0
    def process_raw(self, adsb_ts, adsb_msgs, commb_ts, commb_msgs, tnow=None):
        """process a chunk of adsb and commb messages recieved in the same
        time period.
        """
        if tnow is None:
            tnow = time.time()

        self.t = tnow

        local_updated_acs_buffer = []
        output_buffer = []

        # process adsb message
        for t, msg in zip(adsb_ts, adsb_msgs):
            icao = pms.icao(msg)
            tc = pms.adsb.typecode(msg)

            if icao not in self.acs:
                self.acs[icao] = {
                    'live': None,
                    'call': None,
                    'lat': None,
                    'lon': None,
                    'alt': None,
                    'gs': None,
                    'trk': None,
                    'roc': None,
                    'tas': None,
                    'roll': None,
                    'rtrk': None,
                    'ias': None,
                    'mach': None,
                    'hdg': None,
                    'ver': None,
                    'HPL': None,
                    'RCu': None,
                    'RCv': None,
                    'HVE': None,
                    'VVE': None,
                    'Rc': None,
                    'VPL': None,
                    'EPU': None,
                    'VEPU': None,
                    'HFOMr': None,
                    'VFOMr': None,
                    'PE_RCu': None,
                    'PE_VPL': None,
                }

            self.acs[icao]['t'] = t
            self.acs[icao]['live'] = int(t)

            if 1 <= tc <= 4:
                cs = pms.adsb.callsign(msg)
                self.acs[icao]['call'] = cs
                output_buffer.append([t, icao, 'cs', cs])

            if (5 <= tc <= 8) or (tc == 19):
                vdata = pms.adsb.velocity(msg)
                if vdata is None:
                    continue

                spd, trk, roc, tag = vdata
                if tag != 'GS':
                    continue
                if (spd is None) or (trk is None):
                    continue

                self.acs[icao]['gs'] = spd
                self.acs[icao]['trk'] = trk
                self.acs[icao]['roc'] = roc
                self.acs[icao]['tv'] = t

                output_buffer.append([t, icao, 'gs', spd])
                output_buffer.append([t, icao, 'trk', trk])
                output_buffer.append([t, icao, 'roc', roc])

            if (5 <= tc <= 18):
                oe = pms.adsb.oe_flag(msg)
                self.acs[icao][oe] = msg
                self.acs[icao]['t' + str(oe)] = t

                if ('tpos' in self.acs[icao]) and (t - self.acs[icao]['tpos'] <
                                                   180):
                    # use single message decoding
                    rlat = self.acs[icao]['lat']
                    rlon = self.acs[icao]['lon']
                    latlon = pms.adsb.position_with_ref(msg, rlat, rlon)
                elif ('t0' in self.acs[icao]) and ('t1' in self.acs[icao]) and \
                     (abs(self.acs[icao]['t0'] - self.acs[icao]['t1']) < 10):
                    # use multi message decoding
                    try:
                        latlon = pms.adsb.position(self.acs[icao][0],
                                                   self.acs[icao][1],
                                                   self.acs[icao]['t0'],
                                                   self.acs[icao]['t1'],
                                                   self.lat0, self.lon0)
                    except:
                        # mix of surface and airborne position message
                        continue
                else:
                    latlon = None

                if latlon is not None:
                    self.acs[icao]['tpos'] = t
                    self.acs[icao]['lat'] = latlon[0]
                    self.acs[icao]['lon'] = latlon[1]

                    alt = pms.adsb.altitude(msg)
                    self.acs[icao]['alt'] = alt

                    output_buffer.append([t, icao, 'lat', latlon[0]])
                    output_buffer.append([t, icao, 'lon', latlon[1]])
                    output_buffer.append([t, icao, 'alt', alt])

                    local_updated_acs_buffer.append(icao)

            # Uncertainty & accuracy
            ac = self.acs[icao]

            if 9 <= tc <= 18:
                ac['nic_bc'] = pms.adsb.nic_b(msg)

            if (5 <= tc <= 8) or (9 <= tc <= 18) or (20 <= tc <= 22):
                ac['HPL'], ac['RCu'], ac['RCv'] = pms.adsb.nuc_p(msg)

                if (ac['ver'] == 1) and ('nic_s' in ac.keys()):
                    ac['Rc'], ac['VPL'] = pms.adsb.nic_v1(msg, ac['nic_s'])
                elif (ac['ver'] == 2) and ('nic_a'
                                           in ac.keys()) and ('nic_bc'
                                                              in ac.keys()):
                    ac['Rc'] = pms.adsb.nic_v2(msg, ac['nic_a'], ac['nic_bc'])

            if tc == 19:
                ac['HVE'], ac['VVE'] = pms.adsb.nuc_v(msg)
                if ac['ver'] in [1, 2]:
                    ac['HFOMr'], ac['VFOMr'] = pms.adsb.nac_v(msg)

            if tc == 29:
                ac['PE_RCu'], ac['PE_VPL'], ac['base'] = pms.adsb.sil(
                    msg, ac['ver'])
                ac['EPU'], ac['VEPU'] = pms.adsb.nac_p(msg)

            if tc == 31:
                ac['ver'] = pms.adsb.version(msg)
                ac['EPU'], ac['VEPU'] = pms.adsb.nac_p(msg)
                ac['PE_RCu'], ac['PE_VPL'], ac['sil_base'] = pms.adsb.sil(
                    msg, ac['ver'])

                if ac['ver'] == 1:
                    ac['nic_s'] = pms.adsb.nic_s(msg)
                elif ac['ver'] == 2:
                    ac['nic_a'], ac['nic_bc'] = pms.adsb.nic_a_c(msg)

        # process commb message
        for t, msg in zip(commb_ts, commb_msgs):
            icao = pms.icao(msg)

            if icao not in self.acs:
                continue

            bds = pms.bds.infer(msg)

            if bds == 'BDS50':
                roll50 = pms.commb.roll50(msg)
                trk50 = pms.commb.trk50(msg)
                rtrk50 = pms.commb.rtrk50(msg)
                gs50 = pms.commb.gs50(msg)
                tas50 = pms.commb.tas50(msg)

                self.acs[icao]['t50'] = t
                if tas50:
                    self.acs[icao]['tas'] = tas50
                    output_buffer.append([t, icao, 'tas50', tas50])
                if roll50:
                    self.acs[icao]['roll'] = roll50
                    output_buffer.append([t, icao, 'roll50', roll50])
                if rtrk50:
                    self.acs[icao]['rtrk'] = rtrk50
                    output_buffer.append([t, icao, 'rtrk50', rtrk50])

                if trk50:
                    output_buffer.append([t, icao, 'trk50', trk50])
                if gs50:
                    output_buffer.append([t, icao, 'gs50', gs50])

            elif bds == 'BDS60':
                ias60 = pms.commb.ias60(msg)
                hdg60 = pms.commb.hdg60(msg)
                mach60 = pms.commb.mach60(msg)
                roc60baro = pms.commb.vr60baro(msg)
                roc60ins = pms.commb.vr60ins(msg)

                if ias60 or hdg60 or mach60:
                    self.acs[icao]['t60'] = t
                if ias60:
                    self.acs[icao]['ias'] = ias60
                if hdg60:
                    self.acs[icao]['hdg'] = hdg60
                if mach60:
                    self.acs[icao]['mach'] = mach60

                if roc60baro:
                    output_buffer.append([t, icao, 'roc60baro', roc60baro])
                if roc60ins:
                    output_buffer.append([t, icao, 'roc60ins', roc60ins])

        # clear up old data
        for icao in list(self.acs.keys()):
            if self.t - self.acs[icao]['live'] > self.cache_timeout:
                del self.acs[icao]
                continue

        if self.dumpto is not None:
            dh = str(datetime.datetime.now().strftime("%Y%m%d_%H"))
            fn = self.dumpto + '/pymodes_dump_%s.csv' % dh
            output_buffer.sort(key=lambda x: x[0])
            with open(fn, "a") as f:
                writer = csv.writer(f)
                writer.writerows(output_buffer)

        return