I just learned that, at least in the US, the ICAO hex and N number are mathematically linked. I don’t know the math, but if that formula is publicly available, a feature could be added to dump1090. With the ICAO hex, you could determine the N number without a database. I would think this would be helpful translating commercial flight identifiers into registration numbers.
I’ve been fiddling with some basic decoder functions for US & Canadian aircraft. When new aircraft objects are created in dump1090, I made it pre-fill the callsign field with the registration. That’s not really ideal though, because if the craft broadcasts a bogus callsign it will overwrite it. Also you might want to know the registration and callsign/flight separately.
Would it be better to add a new registration field to the aircraft struct & json?
Or leave dump1090 alone and just calculate the registration on the javascript side? (then you wouldn’t see it in interactive mode)
hmm…
I wonder what other countries have a known ICAO->Tail# pattern.
Right now, if I want to know more about an aircraft with out an N number listed, I have to click on the airframe link, then copy and paste the N number listed on that site into FA. It would be nice if that was automatically handled and skipping the airframe site. I think having everything listed as N number would be good. I only care about GA AC, so I’m not sure many would agree with me.
or… Maybe those AC with a flight #, get the n number added in the details at the top of the window when clicked on.
In any case, it would be nice for a link to be available to lookup the aircraft on FA.
@BartJr: this would fit well on the JavaScript side. It already loads registration data from a static db, computing the registration can be done around the same point.
edit: specifically, you could add it around here: github.com/mutability/dump1090/ … ect.js#L42
The DB lookup will then override the calculated value if it has data.
I haven’t been able to crack the code for the math on it, however it is a mathematically linked function that I believe I have generated a list based on once. I got really bored one day and wrote a bash script to scrape the FAAs registration database and update my basestation.sqb file. It would probably be somewhat trivial to set up dump1090 to query the SQLite database for the information, however I don’t use the dump1090 interface and really don’t have much interest in doing so.
If anyone wants the script to download the DB, I can probably give it to you, however it’s coded to ‘bypass’ the function that seems to deter scripted downloads, so I don’t really want to put it out on the internet.
There is room for improvement on the whole thing (instead of starting with a blank sqb file, copy the running one, MERGE the info from the FAA and replace the running one) but it worked well enough for my purposes.
It DOES appear that VRS now can dynamically obtain the information automatically and update the sqb file, so that’s what I’m using now.
Here is some Python code that I wrote to go to / from N to ICAO. It is based on looking at the structure of BartJr’s table. Spot-checking a few flights on the air it seems to match. This has not been extensively tested and may have errors. Also there is no protection against invalid inputs in the tail to ICAO routine.
The general principle is that an N number has one to three digits after the N. The first digit is never a zero. These are most significant in setting the ICAO number. A number N2nnxx wiil always be exactly 101711 (decimal) away from its N1nnxx counterpart. After this one, two, or three digit number, a suffix of zero to two letters can be applied. If there are 3 digits after the N, the suffix may contain numbers, but if the first digit of the suffix is a letter, the second one (if present) must also be a letter (“N123A1” is illegal). This gives the effect of a 4 or 5 digit N number, but actually internally these are extensions of a 3 digit number with what I call a “base 35” suffix.
base9 = '123456789' # The first digit (after the "N") is always one of these.
base10 = '0123456789' # The possible second and third digits are one of these.
# Note that "I" and "O" are never used as letters, to prevent confusion with "1" and "0"
base34 = 'ABCDEFGHJKLMNPQRSTUVWXYZ0123456789'
icaooffset = 0xA00001 # The lowest possible number, N1, is this.
b1 = 101711 # basis between N1... and N2...
b2 = 10111 # basis between N10.... and N11....
def suffix(rem):
""" Produces the alpha(numeric) suffix from a number 0 - 950 """
if rem == 0:
suf = ''
else:
if rem <= 600: #Class A suffix -- only letters.
rem = rem - 1
suf = base34[rem // 25]
if rem % 25 > 0:
suf = suf + base34(rem % 25) - 1] # second class A letter, if present.
else: #rem > 600 : First digit of suffix is a number. Second digit may be blank, letter, or number.
rem = rem - 601
suf = base10[rem // 35]
if rem % 35 > 0:
suf = suf + base34(rem % 35) - 1]
return suf
def enc_suffix(suf):
""" Produces a remainder from a 0 - 2 digit suffix.
No error checking. Using illegal strings will have strange results."""
if len(suf) == 0:
return 0
r0 = base34.find(suf[0])
if len(suf) == 1:
r1 = 0
else:
r1 = base34.find(suf[1]) + 1
if r0 < 24: # first char is a letter, use base 25
return r0 * 25 + r1 + 1
else: # first is a number -- base 35.
return r0 * 35 + r1 - 239
def icao_to_tail(icao):
if (icao < 0) or (icao > 0xadf7c7):
return "Undefined"
icao = icao - icaooffset
d1 = icao // b1
nnum = 'N' + base9[d1]
r1 = icao % b1
if r1 < 601:
nnum = nnum + suffix(r1) # of the form N1ZZ
else:
d2 = (r1 - 601) // b2 # find second digit.
nnum = nnum + base10[d2]
r2 = (r1 - 601) % b2 # and residue after that
if r2 < 601: # No third digit. (form N12ZZ)
nnum = nnum + suffix(r2)
else:
d3 = (r2 - 601) // 951 # Three-digits have extended suffix.
r3 = (r2 - 601) % 951
nnum = nnum + base10[d3] + suffix(r3)
return nnum
def tail_to_icao(tail):
if tail[0] != 'N':
return -1
icao = icaooffset
icao = icao + base9.find(tail[1]) * b1
if len(tail) == 2: # simple 'N3' etc.
return icao
d2 = base10.find(tail[2])
if d2 == -1: # Form N1A
icao = icao + enc_suffix(tail[2:4])
return icao
else: # Form N11... or N111..
icao = icao + d2 * b2 + 601
d3 = base10.find(tail[3])
if d3 > -1: #Form N111 Suffix is base 35.
icao = icao + d3 * 951 + 601
icao = icao + enc_suffix(tail[4:6])
return icao
else: #Form N11A
icao = icao + enc_suffix(tail[3:5])
return icao
That looks like the same basic algorithm as my python code which I used to generate the table (though yours is better commented :mrgreen: )
#1: 1-9 * 101711
#2: _=601, 0-9*(9510+601)
az = list('ABCDEFGHJKLMNPQRSTUVWXYZ')
baz = ''] + az
na = map(str,range(10))
bazn = ''] + az + map(str,range(10))
def az1(i): #601
if i == 0:
return ''
else:
i -= 1
return az* + baz*
def hex_to_n(h):
s = 'N'
i = int(h)-0xa00001
s += str(i/101711 + 1)
i %= 101711
if i < 601:
s += az1(i)
else:
i -= 601
s += str(i/10111)
i %= 10111
if i < 601:
s += az1(i)
else:
i -= 601
s += str(i/951)
i %= 951
if i < 601:
s += az1(i)
else:
i -= 601
s += na* + bazn*
return s
No need to scrape. They have a direct download of the entire FAA database, though you have to do some minor database-foo to correlate the interesting data from multiple files.
So is there a script I can run that would convert ICAO numbers to N numbers which would display on my local network connection instated of have the N field blank? Would that also mean that more planes would be trackable with the airplane icon and tail instead of just airliners? I guess what I am missing and would like to track is VFR traffic that is sending out ADS-B while they do appear sometimes I am not able to determine most of the times what my receiver is picking up if they are sq 1200
From the publicly available FAA tie-up data one can easily figure out what the algorithms are that relate American N numbers to their ICAO hex address - there are 24 algorithms for the 12 categories of 915399 possible N numbers. I turned these into a little and superfast Windows commandline application which works two-ways, N number <–> ICAO address. If somebody is interested, just ask for it : mailto:blackbird@inboxalias.com. The derived algorithms are available too (in Dutch only). They were thoroughly tested : the FAA data were generated both ways and all matched.