Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added DIS message logger to ./examples/dis-logger #63

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions examples/dis-logger/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import tkinter as tk
from tkinter import ttk
from datetime import datetime
import threading
import sqlite3

lock = threading.Lock()

connection = sqlite3.connect('dis_messages_database.db')

class App(tk.Tk):
def __init__(self):
super().__init__()
self.title('DIS Logger')

table = ttk.Treeview(self, columns=("num", "time", "type", "src", "dst", "ent_id", "ent_marking"), show = 'headings')
self.table = table

# Set heading text
table.heading('num', text='No.')
table.heading('time', text='Time')
table.heading('type', text='Message Type')
table.heading('src', text='Source')
table.heading('dst', text='Destination')
table.heading('ent_id', text='Entity ID')
table.heading('ent_marking', text='Entity Marking')

# Set column widths
table.column('num', width=50)
table.column('ent_id', width=25)

table.pack()
table.bind("<Button-1>", self.on_table_click)

# Set message display
message_display = tk.Text(self, height=10, width=60)
self.message_display = message_display
message_display.pack(pady=10)
message_display.insert(tk.END, "Click on a table entry to view more")

# Setup database
cursor = connection.cursor()
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
tables = cursor.fetchall()

for table_name in tables:
cursor.execute(f"DROP TABLE IF EXISTS {table_name[0]};")

cursor.execute('''
CREATE TABLE IF NOT EXISTS messages (
number INT PRIMARY KEY,
time VARCHAR(255),
type VARCHAR(255),
source_address VARCHAR(255),
source_port VARCHAR(255),
destination_address VARCHAR(255),
destination_port VARCHAR(255),
entity_id INT,
entity_marking VARCHAR(255),
latitude FLOAT,
longitude FLOAT,
altitude FLOAT
)
''')

connection.commit()
cursor.close()


def on_table_click(self, event):
item_id = self.table.identify_row(event.y)
if item_id:
item_values = self.table.item(item_id, 'values')
item_number = item_values[0]
self.message_display.insert(tk.END, item_number)

# Get entry based on number in table
connection = sqlite3.connect('dis_messages_database.db')
cursor = connection.cursor()
cursor.execute("SELECT * FROM messages WHERE number=?", (item_number,))
entry = cursor.fetchall()[0]
cursor.close()

# Form message to be displayed
message = ("Received {}".format(entry[2]) + " at {}\n".format(entry[1])
+ " Sending Addr. : {}\n".format(entry[3])
+ " Sending Port : {}\n".format(entry[4])
+ " Destination Addr.: {}\n".format(entry[5])
+ " Destination Port : {}\n".format(entry[6])
+ " Entity Id : {}\n".format(entry[7])
+ " Entity Marking : {}\n".format(entry[8])
+ " Latitude : {:.5f} degrees\n".format(entry[9])
+ " Longitude : {:.5f} degrees\n".format(entry[10])
+ " Altitude : {:.0f} meters\n".format(entry[11])
)

# Show message in message display
self.message_display.delete(1.0, tk.END)
self.message_display.insert(tk.END, message)


def add_entry(self, entry):
lock.acquire()

# Get message info from entry
num = len(self.table.get_children())
time = datetime.now()
type = entry.type
src_addr = entry.src_addr
dst_addr = entry.dst_addr
ent_id = entry.entityID
ent_marking = entry.marking
latitude = entry.latitude
longitude = entry.longitude
altitude = entry.altitude

# Add message to table
data = (num, time, type, src_addr, dst_addr, ent_id, ent_marking)
self.table.insert(parent='', index=0, values = data)

# Add message to database
connection = sqlite3.connect('dis_messages_database.db')
cursor = connection.cursor()
db_entry = (num, time, type, src_addr, dst_addr, ent_id, ent_marking, latitude, longitude, altitude)
cursor.execute('INSERT INTO messages (number, time, type, source_address, destination_address, entity_id, entity_marking, latitude, longitude, altitude) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', db_entry)
connection.commit()
cursor.close()

lock.release()
130 changes: 130 additions & 0 deletions examples/dis-logger/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
from scapy.all import sniff
import threading
from app import *

from opendis.dis7 import *
from opendis.RangeCoordinates import *
from opendis.PduFactory import createPdu

app = None
gps = GPS()
quitEvent = threading.Event()

class DISMessageInfo:
def __init__(self, pdu, src_addr, dst_addr, src_port, dst_port):
self.src_addr = src_addr
self.dst_addr = dst_addr
self.src_port = src_port
self.dst_port = dst_port

pduTypeName = pdu.__class__.__name__
self.type = pduTypeName
self.type_number = pdu.pduType

# PduTypeDecoders.EntityStatePdu is type 1
if pdu.pduType == 1:
loc = (pdu.entityLocation.x,
pdu.entityLocation.y,
pdu.entityLocation.z,
pdu.entityOrientation.psi,
pdu.entityOrientation.theta,
pdu.entityOrientation.phi
)
try:
body = gps.ecef2llarpy(*loc)
except:
body = [0,0,0]

self.latitude = rad2deg(body[0])
self.longitude = rad2deg(body[1])
self.altitude = body[2]

marking_asci = list(pdu.marking.characters)
marking_string = ""

print(marking_asci)
for i in marking_asci:
try:
if i == 0:
break

marking_string += chr(i)
except Exception:
break

self.entityID = pdu.entityID.entityID
self.marking = marking_string

def __str__(self):
if self.type_number == 1:
return ("Received {}\n".format(self.type)
+ " Sending Addr. : {}\n".format(self.src_addr)
+ " Sending Port : {}\n".format(self.src_port)
+ " Destination Addr.: {}\n".format(self.dst_addr)
+ " Destination Port : {}\n".format(self.dst_port)
+ " Entity Id : {}\n".format(self.entityID)
+ " Entity Marking : {}\n".format(self.marking)
+ " Latitude : {:.2f} degrees\n".format(self.latitude)
+ " Longitude : {:.2f} degrees\n".format(self.longitude)
+ " Altitude : {:.0f} meters\n".format(self.altitude)
)
else:
return ""


def process_packet(packet):
"""
function that takes in packet, processes it into a DIS UDP message, and prints out data if
its of EntityStatePdu type.
"""

# Check if packet contains UDP layer
if packet.haslayer('UDP'):
udp_layer = packet['UDP']
src_port = udp_layer.sport
dst_port = udp_layer.dport

try:
ip_layer = packet['IP']
src_addr = ip_layer.src
dst_addr = ip_layer.dst
except:
src_addr = "None"
dst_addr = "None"

# DIS traffic only on port 3000
if dst_port == 3000:
data = bytes(udp_layer.payload)

pdu = createPdu(data)
message_info = DISMessageInfo(pdu, src_addr, dst_addr, src_port, dst_port)
if app != None:
app.add_entry(message_info)
print(message_info)


def stop_sniffing(x):
return quitEvent.is_set()


def sniff_for_traffic():
print("Listening for DIS traffic...")
sniff(filter="udp and multicast", prn=process_packet, stop_filter=stop_sniffing)


def main():
global app
sniff_thread = threading.Thread(target=sniff_for_traffic)
sniff_thread.start()

try:
app = App()
app.mainloop()
except:
quitEvent.set()

quitEvent.set()
sniff_thread.join()

if __name__=="__main__":
main()