diff --git a/pyModeS/extra/tcpclient.py b/pyModeS/extra/tcpclient.py index 9c90441..47e740b 100644 --- a/pyModeS/extra/tcpclient.py +++ b/pyModeS/extra/tcpclient.py @@ -6,6 +6,7 @@ import time import pyModeS as pms import traceback import zmq +import math class TcpClient(object): @@ -149,6 +150,103 @@ class TcpClient(object): messages.append([msg, ts]) return messages + def read_beast_buffer_rssi_piaware(self): + """Handle mode-s beast data type. + + "1" : 6 byte MLAT timestamp, 1 byte signal level, + 2 byte Mode-AC + "2" : 6 byte MLAT timestamp, 1 byte signal level, + 7 byte Mode-S short frame + "3" : 6 byte MLAT timestamp, 1 byte signal level, + 14 byte Mode-S long frame + "4" : 6 byte MLAT timestamp, status data, DIP switch + configuration settings (not on Mode-S Beast classic) + : true 0x1a + is 0x1a, and "1", "2" and "3" are 0x31, 0x32 and 0x33 + + timestamp: + wiki.modesbeast.com/Radarcape:Firmware_Versions#The_GPS_timestamp + """ + messages_mlat = [] + msg = [] + i = 0 + + # process the buffer until the last divider 0x1a + # then, reset the self.buffer with the remainder + + while i < len(self.buffer): + if self.buffer[i : i + 2] == [0x1A, 0x1A]: + msg.append(0x1A) + i += 1 + elif (i == len(self.buffer) - 1) and (self.buffer[i] == 0x1A): + # special case where the last bit is 0x1a + msg.append(0x1A) + elif self.buffer[i] == 0x1A: + if i == len(self.buffer) - 1: + # special case where the last bit is 0x1a + msg.append(0x1A) + elif len(msg) > 0: + messages_mlat.append(msg) + msg = [] + else: + msg.append(self.buffer[i]) + i += 1 + + # save the reminder for next reading cycle, if not empty + if len(msg) > 0: + reminder = [] + for i, m in enumerate(msg): + if (m == 0x1A) and (i < len(msg) - 1): + # rewind 0x1a, except when it is at the last bit + reminder.extend([m, m]) + else: + reminder.append(m) + self.buffer = [0x1A] + msg + else: + self.buffer = [] + + # extract messages + messages = [] + for mm in messages_mlat: + ts = time.time() + + msgtype = mm[0] + # print(''.join('%02X' % i for i in mm)) + + if msgtype == 0x32: + # Mode-S Short Message, 7 byte, 14-len hexstr + msg = "".join("%02X" % i for i in mm[8:15]) + elif msgtype == 0x33: + # Mode-S Long Message, 14 byte, 28-len hexstr + msg = "".join("%02X" % i for i in mm[8:22]) + else: + # Other message tupe + continue + + if len(msg) not in [14, 28]: + continue + + ''' + we get the raw 0-255 byte value (raw_rssi = mm[7]) + we scale it to 0.0 - 1.0 (voltage = raw_rssi / 255) + we convert it to a dBFS power value (rolling the squaring of the voltage into the dB calculation) + ''' + + df = pms.df(msg) + raw_rssi = mm[7] # eighth byte of Mode-S message should contain RSSI value + rssi_ratio = raw_rssi / 255 + signalLevel = rssi_ratio ** 2 + dbfs_rssi = 10 * math.log10(signalLevel) + + # skip incomplete message + if df in [0, 4, 5, 11] and len(msg) != 14: + continue + if df in [16, 17, 18, 19, 20, 21, 24] and len(msg) != 28: + continue + + messages.append([msg, dbfs_rssi, ts]) + return messages + def read_skysense_buffer(self): """Skysense stream format.