Merge pull request #35 from Ka-zam/skysense
Enable skysense raw type in the streamer.
This commit is contained in:
commit
f5c2b36209
@ -72,13 +72,13 @@ Supports **Mode-S Beast** and **AVR** raw stream
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
modeslive --server [server_address] --port [tcp_port] --rawtype [beast_or_avr] --latlon [lat] [lon]
|
modeslive --server [server_address] --port [tcp_port] --rawtype [beast,avr,skysense] --latlon [lat] [lon]
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
--server SERVER server address or IP
|
--server SERVER server address or IP
|
||||||
--port PORT raw data port
|
--port PORT raw data port
|
||||||
--rawtype RAWTYPE beast or avr
|
--rawtype RAWTYPE beast, avr or skysense
|
||||||
--latlon LAT LON receiver position
|
--latlon LAT LON receiver position
|
||||||
--show-uncertainty display uncertaint values, default off
|
--show-uncertainty display uncertaint values, default off
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ def np2bin(npbin):
|
|||||||
def df(msg):
|
def df(msg):
|
||||||
"""Decode Downlink Format vaule, bits 1 to 5."""
|
"""Decode Downlink Format vaule, bits 1 to 5."""
|
||||||
msgbin = hex2bin(msg)
|
msgbin = hex2bin(msg)
|
||||||
return bin2int(msgbin[0:5])
|
return min( bin2int(msgbin[0:5]) , 24 )
|
||||||
|
|
||||||
|
|
||||||
def crc(msg, encode=False):
|
def crc(msg, encode=False):
|
||||||
|
@ -20,8 +20,8 @@ class BaseClient(Thread):
|
|||||||
self.port = port
|
self.port = port
|
||||||
self.buffer = []
|
self.buffer = []
|
||||||
self.rawtype = rawtype
|
self.rawtype = rawtype
|
||||||
if self.rawtype not in ['avr', 'beast']:
|
if self.rawtype not in ['avr', 'beast', 'skysense']:
|
||||||
print("rawtype must be either avr or beast")
|
print("rawtype must be either avr, beast or skysense")
|
||||||
os._exit(1)
|
os._exit(1)
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
@ -144,11 +144,89 @@ class BaseClient(Thread):
|
|||||||
messages.append([msg, ts])
|
messages.append([msg, ts])
|
||||||
return messages
|
return messages
|
||||||
|
|
||||||
|
def read_skysense_buffer(self):
|
||||||
|
"""
|
||||||
|
----------------------------------------------------------------------------------
|
||||||
|
Field SS MS MS MS MS MS MS MS MS MS MS MS MS MS MS TS TS TS TS TS TS RS RS RS
|
||||||
|
----------------------------------------------------------------------------------
|
||||||
|
Position: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
||||||
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
SS field - Start character
|
||||||
|
Position 0:
|
||||||
|
1 byte = 8 bits
|
||||||
|
Start character '$'
|
||||||
|
|
||||||
|
MS field - Payload
|
||||||
|
Postion 1 through 14:
|
||||||
|
14 bytes = 112 bits
|
||||||
|
Mode-S payload
|
||||||
|
In case of DF types that only carry 7 bytes of information position 8 through 14 are set to 0x00.
|
||||||
|
|
||||||
|
TS field - Time stamp
|
||||||
|
Position 15 through 20:
|
||||||
|
6 bytes = 48 bits
|
||||||
|
Time stamp with fields as:
|
||||||
|
|
||||||
|
Lock Status - Status of internal time keeping mechanism
|
||||||
|
Equal to 1 if operating normally
|
||||||
|
Bit 47 - 1 bit
|
||||||
|
|
||||||
|
Time of day in UTC seconds, between 0 and 86399
|
||||||
|
Bits 46 through 30 - 17 bits
|
||||||
|
|
||||||
|
Nanoseconds into current second, between 0 and 999999999
|
||||||
|
Bits 29 through 0 - 30 bits
|
||||||
|
|
||||||
|
RS field - Signal Level
|
||||||
|
Position 21 through 23:
|
||||||
|
3 bytes = 24 bits
|
||||||
|
RSSI (received signal strength indication) and relative noise level with fields
|
||||||
|
|
||||||
|
RNL, Q12.4 unsigned fixed point binary with 4 fractional bits and 8 integer bits.
|
||||||
|
This is and indication of the noise level of the message. Roughly 40 counts per 10dBm.
|
||||||
|
Bits 23 through 12 - 12 bits
|
||||||
|
|
||||||
|
RSSI, Q12.4 unsigned fixed point binary with 4 fractional bits and 8 integer bits.
|
||||||
|
This is an indication of the signal level of the received message in ADC counts. Roughly 40 counts per 10dBm.
|
||||||
|
Bits 11 through 0 - 12 bits
|
||||||
|
"""
|
||||||
|
SS_MSGLENGTH = 24
|
||||||
|
SS_STARTCHAR = 0x24
|
||||||
|
|
||||||
|
if len(self.buffer) <= SS_MSGLENGTH:
|
||||||
|
return None
|
||||||
|
|
||||||
|
messages = []
|
||||||
|
while len(self.buffer) > SS_MSGLENGTH:
|
||||||
|
i = 0
|
||||||
|
if self.buffer[i] == SS_STARTCHAR and self.buffer[i+SS_MSGLENGTH] == SS_STARTCHAR:
|
||||||
|
i += 1
|
||||||
|
if (self.buffer[i]>>7):
|
||||||
|
#Long message
|
||||||
|
payload = self.buffer[i:i+14]
|
||||||
|
else:
|
||||||
|
#Short message
|
||||||
|
payload = self.buffer[i:i+7]
|
||||||
|
msg = ''.join('%02X' % j for j in payload)
|
||||||
|
i += 14 #Both message types use 14 bytes
|
||||||
|
tsbin = self.buffer[i:i+6]
|
||||||
|
sec = ( (tsbin[0] & 0x7f) << 10) | (tsbin[1] << 2 ) | (tsbin[2] >> 6)
|
||||||
|
nano = ( (tsbin[2] & 0x3f) << 24) | (tsbin[3] << 16) | (tsbin[4] << 8) | tsbin[5]
|
||||||
|
ts = sec + nano*1.0e-9
|
||||||
|
i += 6
|
||||||
|
#Signal and noise level - Don't care for now
|
||||||
|
i += 3
|
||||||
|
self.buffer = self.buffer[SS_MSGLENGTH:]
|
||||||
|
messages.append( [msg,ts] )
|
||||||
|
else:
|
||||||
|
self.buffer = self.buffer[1:]
|
||||||
|
return messages
|
||||||
|
|
||||||
def handle_messages(self, messages):
|
def handle_messages(self, messages):
|
||||||
"""re-implement this method to handle the messages"""
|
"""re-implement this method to handle the messages"""
|
||||||
for msg, t in messages:
|
for msg, t in messages:
|
||||||
print("%f %s" % (t, msg))
|
print("%15.9f %s" % (t, msg))
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
sock = self.connect()
|
sock = self.connect()
|
||||||
@ -172,6 +250,8 @@ class BaseClient(Thread):
|
|||||||
messages = self.read_beast_buffer()
|
messages = self.read_beast_buffer()
|
||||||
elif self.rawtype == 'avr':
|
elif self.rawtype == 'avr':
|
||||||
messages = self.read_avr_buffer()
|
messages = self.read_avr_buffer()
|
||||||
|
elif self.rawtype == 'skysense':
|
||||||
|
messages = self.read_skysense_buffer()
|
||||||
|
|
||||||
if not messages:
|
if not messages:
|
||||||
continue
|
continue
|
||||||
@ -188,11 +268,11 @@ class BaseClient(Thread):
|
|||||||
print("Unexpected Error:", e)
|
print("Unexpected Error:", e)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# for testing purpose only
|
# for testing purpose only
|
||||||
host = sys.argv[1]
|
host = sys.argv[1]
|
||||||
port = int(sys.argv[2])
|
port = int(sys.argv[2])
|
||||||
client = BaseClient(host=host, port=port)
|
rawtype = sys.argv[3]
|
||||||
|
client = BaseClient(host=host, port=port, rawtype=rawtype)
|
||||||
client.daemon = True
|
client.daemon = True
|
||||||
client.run()
|
client.run()
|
||||||
|
2
pyModeS/streamer/modeslive
Normal file → Executable file
2
pyModeS/streamer/modeslive
Normal file → Executable file
@ -21,7 +21,7 @@ COMMB_TS = []
|
|||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('--server', help='server address or IP', required=True)
|
parser.add_argument('--server', help='server address or IP', required=True)
|
||||||
parser.add_argument('--port', help='raw data port', required=True)
|
parser.add_argument('--port', help='raw data port', required=True)
|
||||||
parser.add_argument('--rawtype', help='beast or avr', required=True)
|
parser.add_argument('--rawtype', help='beast, avr or skysense', required=True)
|
||||||
parser.add_argument('--latlon', help='receiver position', nargs=2, metavar=('LAT', 'LON'), required=True)
|
parser.add_argument('--latlon', help='receiver position', nargs=2, metavar=('LAT', 'LON'), required=True)
|
||||||
parser.add_argument('--show-uncertainty', dest='uncertainty', help='display uncertaint values, default off', action='store_true', required=False, default=False)
|
parser.add_argument('--show-uncertainty', dest='uncertainty', help='display uncertaint values, default off', action='store_true', required=False, default=False)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
Loading…
Reference in New Issue
Block a user