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
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
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
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
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
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()
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
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)
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