From b9096dd391e09aa4ae2b76efea2b346fd0f4a551 Mon Sep 17 00:00:00 2001 From: Scratchcat1 Date: Tue, 3 Oct 2017 17:37:25 +0000 Subject: [PATCH] Add files via upload -Enabled async exiting. Exit messages are all sent before waiting to join. -General bug fixes and improvements. -General system stability test passed. 4 Drones, 1 Client, 1 Monitor. - Note: ~8% CPU usage on RPi3 : 4 Drones at 10X speed simulation, printing,connecting. 1 Server with printing. --- AATC_Crypto.py | 2 +- AATC_DB.py | 3 + AATC_GPIO.py | 135 +++++++------ AATC_Monitor_Viewer.py | 58 +++--- AATC_NoFlyZoneGrapher.py | 14 +- AATC_Server_002.py | 408 ++++++++++++++++++++++++++++++++------- AATC_Server_Starter.py | 147 +++++++++----- 7 files changed, 553 insertions(+), 214 deletions(-) diff --git a/AATC_Crypto.py b/AATC_Crypto.py index d79adb5..c3e59bf 100644 --- a/AATC_Crypto.py +++ b/AATC_Crypto.py @@ -112,4 +112,4 @@ def Recv(self): return data #return data[0],data[1],data[2] except Exception as e: - print(e) + print("Error in Cryptor while receiving ",e) diff --git a/AATC_DB.py b/AATC_DB.py index 8345ea9..a18a1c6 100644 --- a/AATC_DB.py +++ b/AATC_DB.py @@ -294,14 +294,17 @@ def MonitorCheckCredentials(self,MonitorName,MonitorPassword): def GetMonitorDrones(self,MonitorID): self.cur.execute("SELECT Drone.* FROM Drone,MonitorPermission WHERE Drone.UserID = MonitorPermission.UserID and MonitorPermission.MonitorID = %s",(MonitorID,)) + self.db_con.commit() return True,str(self.Table_Headers("Drone")),self.cur.fetchall() def GetMonitorFlights(self,MonitorID): self.cur.execute("SELECT Flight.* FROM Flight,Drone,MonitorPermission WHERE Flight.DroneID = Drone.DroneID AND Drone.UserID = MonitorPermission.UserID and MonitorPermission.MonitorID = %s",(MonitorID,)) + self.db_con.commit() return True,str(self.Table_Headers("Flight")),self.cur.fetchall() def GetMonitorFlightWaypoints(self,MonitorID): self.cur.execute("SELECT FlightWaypoints.* FROM FlightWaypoints,Flight,Drone,MonitorPermission WHERE FlightWaypoints.FlightID = Flight.FlightID AND Flight.DroneID = Drone.DroneID AND Drone.UserID = MonitorPermission.UserID and MonitorPermission.MonitorID = %s",(MonitorID,)) + self.db_con.commit() return True,str(self.Table_Headers("FlightWaypoints")),self.cur.fetchall() def GetMonitorID(self,MonitorName): diff --git a/AATC_GPIO.py b/AATC_GPIO.py index 576aa14..9043ac1 100644 --- a/AATC_GPIO.py +++ b/AATC_GPIO.py @@ -8,6 +8,35 @@ ##GPIO.setup(21, GPIO.OUT) #green ##GPIO.setup(26, GPIO.IN) #button +def GPIO_Thread(Thread_Name,GPIO_Queue): + Exit = False + Function = BlankFunction + FuncArgs = () + while not Exit: + try: + FuncReset = Function(Thread_Name,*FuncArgs) #calls the function passed to the thread + + if FuncReset: + Function,FuncArgs = BlankFunction,() #Resets commands. Allows function to exit itself. + + if not GPIO_Queue.empty(): + Data = GPIO_Queue.get() + #GPIO_Queue.task_done() + Command,Arguments = Data[0],Data[1] + + if Command == "Function": + Function, FuncArgs = Arguments[0],Arguments[1] + elif Command == "Exit": + Exit = True + + except Exception as e: + print("Error occured in GPIO_Thread",Thread_Name,".",str(e)) + Function,FuncArgs = BlankFunction,() #Resets commands to prevent large prints + + + + + class Thread_Handle: def __init__(self,Thread_Name,ThreadPointer,Queue): self.Thread_Name = Thread_Name @@ -23,31 +52,36 @@ def Get_ThreadPointer(self): def Get_Queue(self): return self.Queue -class GPIO_Thread_Controller: - def __init__(self,Command_Queue): - print("Creating Thread Controller") + + + + +class Thread_Controller: + def __init__(self,Command_Queue,Name = ""): + print("Creating Thread Controller",Name) + self.Name ="TC"+ Name + " >" self.Command_Queue = Command_Queue self.Threads = {} - def Create_Thread(self,Thread_Name,Process = False): #If Process is True, will use a Process rather than a thread. + def Create_Thread(self,Thread_Name,TargetCommand = GPIO_Thread,TargetArgs = (),Process = False): #If Process is True, will use a Process rather than a thread. if Thread_Name in self.Threads: #Close thread if already exists self.Close_Thread(Thread_Name) if Process: Thread_Queue = multiprocessing.Queue() - threadPointer = multiprocessing.Process(target = GPIO_Thread,args = (Thread_Name,Thread_Queue)) + threadPointer = multiprocessing.Process(target = TargetCommand,args = (Thread_Name,Thread_Queue)+TargetArgs) else: Thread_Queue = queue.Queue() - threadPointer = threading.Thread(target = GPIO_Thread,args = (Thread_Name,Thread_Queue)) + threadPointer = threading.Thread(target = TargetCommand,args = (Thread_Name,Thread_Queue)+TargetArgs) self.Threads[Thread_Name] = Thread_Handle(Thread_Name,threadPointer,Thread_Queue) threadPointer.start() - print(self.Threads) def Close_Thread(self,Thread_Name): - Thread = self.Threads.pop(Thread_Name) - Queue = Thread.Get_Queue() + ClosingThreadHandle = self.Threads.pop(Thread_Name) + Queue = ClosingThreadHandle.Get_Queue() Queue.put(("Exit",())) - print("GPIO Controller closed Thread",Thread_Name) + print(self.Name,"GPIO Controller closed Thread",Thread_Name) + return ClosingThreadHandle #Returns Thread_Handle of thread def PassData(self,Thread_Name,Data): @@ -57,79 +91,68 @@ def PassData(self,Thread_Name,Data): def Main(self): Exit = False while not Exit: -## try: + try: Request = self.Command_Queue.get() #(Thread_Name/Controller command,"Command",Args) self.Command_Queue.task_done() if Request[0] == "Controller": Command,Args = Request[1],Request[2] - if Command == "Create_Thread": + if Command == "Create_Thread": #In total form ("Controller","Create_Thread",(ThreadName,[TargetFunction,TargetArguments])) self.Create_Thread(*Args) elif Command == "Create_Process": self.Create_Thread(*Args, Process = True) elif Command == "Close_Thread": self.Close_Thread(*Args) - elif Command == "Exit": + elif Command == "Exit": #Shutdown everything + self.Reset(*Args) self.Exit = True - elif Command == "Reset": - self.Reset() + elif Command == "Reset": #Shutdown all threads, not controller + self.Reset(*Args) + else: self.PassData(Request[0],(Request[1],Request[2])) - - + except Exception as e: + print(self.Name,"Error in GPIO_Thread_Controller",e) + print(self.Name,"Shutting down") -## except Exception as e: -## print("Error in GPIO_Thread_Controller",e) - - def Reset(self): - print("Reseting GPIO Threading Controller...") + def Reset(self,Wait_Join = False): + print(self.Name,"Reseting GPIO Threading Controller...") Thread_Names = list(self.Threads.keys()) + ThreadHandles = [] for Thread_Name in Thread_Names: - self.Close_Thread(Thread_Name) - print("Reset GPIO Threading Controller") - - - - - - - -def GPIO_Thread(Thread_Name,GPIO_Queue): - Exit = False - Function = BlankFunction - FuncArgs = () - while not Exit: - try: - FuncReset = Function(Thread_Name,*FuncArgs) #calls the function passed to the thread + ClosingThreadHandle = self.Close_Thread(Thread_Name) + ThreadHandles.append(ClosingThreadHandle) - if FuncReset: - Function,FuncArgs = BlankFunction,() #Resets commands. Allows function to exit itself. + if Wait_Join: #In seperate loop to asyncrously call 'Exit' + for ThreadHandle in ThreadHandles: + ThreadPointer = ThreadHandle.Get_ThreadPointer() + ThreadPointer.join() - if not GPIO_Queue.empty(): - Data = GPIO_Queue.get() - #GPIO_Queue.task_done() - Command,Arguments = Data[0],Data[1] - - if Command == "Function": - Function, FuncArgs = Arguments[0],Arguments[1] - elif Command == "Exit": - Exit = True + print(self.Name,"Reset GPIO Threading Controller") - except Exception as e: - print("Error occured in GPIO_Thread",Thread_Name,".",str(e)) - Function,FuncArgs = BlankFunction,() #Resets commands to prevent large prints + + + -def Create_Controller(): - q = queue.Queue() - g = GPIO_Thread_Controller(q) - t = threading.Thread(target = g.Main) +def Create_Controller(process = False): + if process: + q = multiprocessing.Queue() + else: + q = queue.Queue() + + TC = Thread_Controller(q) + + if process: + t = multiprocessing.Process(target = TC.Main) + else: + t = threading.Thread(target = TC.Main) t.start() return q diff --git a/AATC_Monitor_Viewer.py b/AATC_Monitor_Viewer.py index 23316ab..032b799 100644 --- a/AATC_Monitor_Viewer.py +++ b/AATC_Monitor_Viewer.py @@ -1,4 +1,4 @@ -import pygame,AATC_Monitor,time,ast,sys +import pygame,AATC_Monitor,time,ast,sys,random from AATC_Coordinate import * pygame.init() @@ -9,18 +9,32 @@ def GetImage(xSize,ySize,Colour): #Efficiently get images result = pygame.Surface((xSize,ySize)).convert() result.fill(Colour) _images[(xSize,ySize,Colour)]=result -## result_copy = pygame.Surface(result.get_size()) -## result_copy.blit(result,(0,0)) + while len(_images) > 1500: + _images.pop(random.sample(_images.keys(),1)[0]) #If cache is full evict old versions return result#_copy _texts= {} -def GetText(Text,font,AA,Colour): #Efficiently get text - result = _texts.get((Text,font,AA,Colour)) +def GetText(Text,fontParameters,AA,Colour): #Efficiently get text + result = _texts.get((Text,fontParameters,AA,Colour)) if result == None: - result = font.render(Text,AA,Colour) - _images[(Text,font,AA,Colour)]=result + result = GetFont(*fontParameters).render(Text,AA,Colour) + _texts[(Text,fontParameters,AA,Colour)]=result + while len(_texts) > 1500: + _texts.pop(random.sample(_texts.keys(),1)[0]) #If cache is full evict old versions return result + +_fonts = {} +def GetFont(Font,Size): + result = _fonts.get((Font,Size)) + if result == None: + result = pygame.font.Font(Font,Size) + _fonts[(Font,Size)]=result + while len(_fonts) > 1500: + _fonts.pop(random.sample(_fonts.keys(),1)[0]) #If cache is full evict old versions + return result + + def MaxLimit(value,Max): if value > Max: value = Max @@ -81,14 +95,14 @@ def Draw(self): PosY = ((Object.Coords.y- self.CameraCoord.y)/self.CameraCoord.ySize)* self.ypixel ## width,height = Object.Coords.xSize*self.CameraZoom ,Object.Coords.ySize*self.CameraZoom width,height = int(Object.Coords.xSize/self.CameraCoord.xSize*self.xpixel) ,int(Object.Coords.ySize/self.CameraCoord.ySize*self.ypixel) - if width > 0 or height > 0: + if width > 0 and height > 0: width = MaxLimit(width,self.xpixel) height = MaxLimit(height,self.ypixel) font_size = int(100*width/self.xpixel) Object.Make_Image(width,height) # Object has coordinates and size in these coordinates self.gameDisplay.blit(Object.image,(PosX,PosY)) if font_size > 5: - font = pygame.font.Font(None, font_size) #TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS + font = (None, font_size) #TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS Object.Make_CoordsText(font) #TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS Object.Make_Text(font) #TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS Object.Make_Type(font) #TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS#TEST THIS @@ -240,8 +254,8 @@ def MakeSprites(M): -xpixel = 1000 -ypixel = 500 +xpixel = 1200 +ypixel = 700 Refresh_Delay = 60 clock = pygame.time.Clock() pressed = pygame.key.get_pressed @@ -257,11 +271,11 @@ def MakeSprites(M): while True: MonCamera.ResetDrawObject() Sprites = MakeSprites(M) - font = pygame.font.Font(None, 30) + #font = (None, 30) for sprite in Sprites: - sprite.Make_CoordsText(font) - sprite.Make_Text(font) - sprite.Make_Type(font) + #sprite.Make_CoordsText(font) + #sprite.Make_Text(font) + #sprite.Make_Type(font) MonCamera.AddDrawObject(sprite,False) Last_Refresh_Time = time.time() @@ -276,20 +290,6 @@ def MakeSprites(M): print("Monitor exit was called") pygame.quit() sys.exit() - -## elif event.type == pygame.KEYDOWN and event.key == pygame.K_w: #Shift camera -## MonCamera.IncrementCameraCoordY(-0.5/MonCamera.GetZoom()) #/ as Greater zoom means need more fidelety -## elif event.type == pygame.KEYDOWN and event.key == pygame.K_s: -## MonCamera.IncrementCameraCoordY(0.5/MonCamera.GetZoom()) -## elif event.type == pygame.KEYDOWN and event.key == pygame.K_a: -## MonCamera.IncrementCameraCoordX(-0.5/MonCamera.GetZoom()) -## elif event.type == pygame.KEYDOWN and event.key == pygame.K_d: -## MonCamera.IncrementCameraCoordX(0.5/MonCamera.GetZoom()) - -## elif event.type == pygame.KEYDOWN and event.key == pygame.K_q:#Zoom out -## MonCamera.SetZoom(0.9*MonCamera.GetZoom()) -## elif event.type == pygame.KEYDOWN and event.key == pygame.K_e:#Zoom in -## MonCamera.SetZoom(1.1*MonCamera.GetZoom()) elif event.type == pygame.MOUSEBUTTONDOWN: print("Camera details") diff --git a/AATC_NoFlyZoneGrapher.py b/AATC_NoFlyZoneGrapher.py index db467ce..45a32a6 100644 --- a/AATC_NoFlyZoneGrapher.py +++ b/AATC_NoFlyZoneGrapher.py @@ -13,10 +13,11 @@ class NoFlyZoneGrapher: Could use an A/B method to update if file locking occurs where the Updating takes place on one set of data while the other set of data is read from by eg A* pathfinding """ - def __init__(self,KillSwitch,Interval = 36000): + def __init__(self,Thread_Name,Thread_Queue,Interval = 36000): self.DB = AATC_DB.DBConnection() self.Interval = Interval - self.KillSwitch = KillSwitch + self.Thread_Name = Thread_Name + self.Thread_Queue = Thread_Queue graph = AATC_AStar.DynoGraph() graph.ImportGraph() @@ -26,7 +27,8 @@ def __init__(self,KillSwitch,Interval = 36000): self.Main_Loop() def Main_Loop(self): - while not self.KillSwitch.is_set(): + self.Exit = False + while not self.Exit: try: NoFlyZoneData = self.GetNoFlyZones() self.Make_Values(NoFlyZoneData) @@ -34,6 +36,12 @@ def Main_Loop(self): print("Error occured in NoFlyZoneGrapher",e) print("NoFlyZoneGrapher completed. Sleeping...") time.sleep(self.Interval) + + if not self.Thread_Queue.empty(): + data = self.Thread_Queue.get() + Command,Arguments = data[0],data[1] + if Command == "Exit": + self.Exit = True def Mod(self,Coords): return int(Coords.x//self.xSize),int(Coords.y//self.ySize),int(Coords.z//self.zSize) diff --git a/AATC_Server_002.py b/AATC_Server_002.py index c72dcc4..1ecfd2c 100644 --- a/AATC_Server_002.py +++ b/AATC_Server_002.py @@ -41,8 +41,10 @@ def DeltaCoordToMetres(aCoord,bCoord): class UserConnection: - def __init__(self,Connection): + def __init__(self,Thread_Name,Thread_Queue,Connection): self.DB = AATC_DB.DBConnection() + self.Thread_Name = Thread_Name + self.Thread_Queue = Thread_Queue self.con = Connection self.Crypto = AATC_Crypto.Crypter(self.con, mode = "SERVER" ) self.UserID = -1 #Used to identify if has logged in yet @@ -71,27 +73,23 @@ def Connection_Loop(self): Arguments may be converted from Tuple to Dict in future for clarity """ - try: - while self.UserID == -1:#Repeats until logs in + Exit = False + while not Exit: + try: data = self.Recv() - try: - Command,Arguments = data[0],data[1] + Command,Arguments = data[0],data[1] + if self.UserID == -1: if Command == "Login": Sucess,Message,Data = self.Login(Arguments) elif Command == "AddUser": # If adding a new user, one must create it first, then log in seperatly Sucess,Message,Data = self.AddUser(Arguments) + elif Command == "Exit": + Sucess,Message,Data = self.Exit(Arguments) + Exit = True else: Sucess,Message,Data = False,"Command does not exist",[] - except Exception as e: - Sucess,Message,Data = False,"An Error occured"+str(e),[] - print("Error occured with UserID:",str(self.UserID),"Error :",str(e)," Sending failure message") - self.Send((Sucess,Message,Data)) - - Exit = False - while not Exit: - data = self.Recv() - try: - Command,Arguments = data[0],data[1] + + else: if Command == "GetNoFlyZones": Sucess,Message,Data = self.GetNoFlyZones(Arguments) elif Command == "AddNoFlyZone": @@ -166,15 +164,130 @@ def Connection_Loop(self): else: Sucess,Message,Data = False,"Command does not exist",[] print("User tried to use unregistered command") - except Exception as e: - Sucess,Message,Data = False,"An Error occured"+str(e),[] - print("Error occured with UserID:",str(self.UserID),". Error :",str(e),". Sending failure message") + + except Exception as e: + Sucess,Message,Data = False,"An Error occured"+str(e),[] + print("Error occured with UserID:",str(self.UserID),". Error :",str(e),". Sending failure message") + + try: self.Send((Sucess,Message,Data)) - except Exception as e: - if type(e) == BrokenPipeError: + except Exception as e: print("UserID:",self.UserID," disconnected") - else: - print("Serious exception occured with UserID ",self.UserID," Error",e) + Exit = True + + if not self.Thread_Queue.empty(): + data = Thread_Queue.get() + Command,Arguments = data[0],data[1] + if Command == "Exit": + Exit = True + + +## +## try: +## Exit = False +## while self.UserID == -1 and not Exit:#Repeats until logs in +## data = self.Recv() +## try: +## Command,Arguments = data[0],data[1] +## if Command == "Login": +## Sucess,Message,Data = self.Login(Arguments) +## elif Command == "AddUser": # If adding a new user, one must create it first, then log in seperatly +## Sucess,Message,Data = self.AddUser(Arguments) +## else: +## Sucess,Message,Data = False,"Command does not exist",[] +## except Exception as e: +## Sucess,Message,Data = False,"An Error occured"+str(e),[] +## print("Error occured with UserID:",str(self.UserID),"Error :",str(e)," Sending failure message") +## self.Send((Sucess,Message,Data)) +## +## +## while not Exit: +## data = self.Recv() +## try: +## Command,Arguments = data[0],data[1] +## if Command == "GetNoFlyZones": +## Sucess,Message,Data = self.GetNoFlyZones(Arguments) +## elif Command == "AddNoFlyZone": +## Sucess,Message,Data = self.AddNoFlyZone(Arguments) +## elif Command == "RemoveNoFlyZone": +## Sucess,Message,Data = self.RemoveNoFlyZone(Arguments) +## elif Command == "ModifyNoFlyZoneLevel": +## Sucess,Message,Data = self.ModifyNoFlyZoneLevel(Arguments) +## +## elif Command == "AddDrone": +## Sucess,Message,Data = self.AddDrone(Arguments) +## elif Command == "RemoveDrone": +## Sucess,Message,Data = self.RemoveDrone(Arguments) +## elif Command == "GetDroneID": +## Sucess,Message,Data = self.GetDroneID(Arguments) +## elif Command == "GetDroneCredentials": +## Sucess,Message,Data = self.GetDroneCredentials(Arguments) +## elif Command == "SetDroneCredentials": +## Sucess,Message,Data = self.SetDroneCredentials(Arguments) +## elif Command == "CheckDroneOwnership": +## Sucess,Message,Data = self.CheckDroneOwnership(Arguments) +## elif Command == "GetDroneInfo": +## Sucess,Message,Data = self.GetDroneInfo(Arguments) +## elif Command == "GetDronesUser": +## Sucess,Message,Data = self.GetDronesUser(Arguments) +## elif Command == "GetDronesAll": +## Sucess,Message,Data = self.GetDronesAll(Arguments) +## +## elif Command == "Login": #Can then change UserID without restarting, UserID is changed as well as components on client side +## Sucess,Message,Data = self.Login(Arguments) +## elif Command == "GetUserID": +## Sucess,Message,Data = self.GetUserID(Arguments) +## elif Command == "GetUsername": +## Sucess,Message,Data = self.GetUsername(Arguments) +## elif Command == "SetUserPublicVisibleFlights": +## Sucess,Message,Data = self.SetUserPublicVisibleFlights(Arguments) +## elif Command == "SetAccountType": +## Sucess,Message,Data = self.SetAccountType(Arguments) +## +## elif Command == "GetFlightsUser": +## Sucess,Message,Data = self.GetFlightsUser(Arguments) +## elif Command == "GetFlightsAll": +## Sucess,Message,Data = self.GetFlightsAll(Arguments) +## elif Command == "AddFlight": +## Sucess,Message,Data = self.AddFlight(Arguments) +## elif Command == "RemoveFlight": +## Sucess,Message,Data = self.RemoveFlight(Arguments) +## +## elif Command == "GetFlightWaypointsUser": +## Sucess,Message,Data = self.GetFlightWaypointsUser(Arguments) +## elif Command == "GetFlightWaypointsAll": +## Sucess,Message,Data = self.GetFlightWaypointsAll(Arguments) +## +## elif Command == "GetMonitorID": +## Sucess,Message,Data = self.GetMonitorID(Arguments) +## elif Command == "GetMonitorName": +## Sucess,Message,Data = self.GetMonitorName(Arguments) +## +## elif Command == "AddMonitorPermission": +## Sucess,Message,Data = self.AddMonitorPermission(Arguments) +## elif Command == "RemoveMonitorPermission": +## Sucess,Message,Data = self.RemoveMonitorPermission(Arguments) +## elif Command == "ModifyMonitorPermissionDate": +## Sucess,Message,Data = self.ModifyMonitorPermissionDate(Arguments) +## elif Command == "GetMonitorPermissionUser": +## Sucess,Message,Data = self.GetMonitorPermissionUser(Arguments) +## +## elif Command == "Exit": +## Sucess,Message,Data = self.Exit(Arguments) +## Exit = True +## #Else if command doesnt exist send back Failure +## else: +## Sucess,Message,Data = False,"Command does not exist",[] +## print("User tried to use unregistered command") +## except Exception as e: +## Sucess,Message,Data = False,"An Error occured"+str(e),[] +## print("Error occured with UserID:",str(self.UserID),". Error :",str(e),". Sending failure message") +## self.Send((Sucess,Message,Data)) +## except Exception as e: +## if type(e) == BrokenPipeError: +## print("UserID:",self.UserID," disconnected") +## else: +## print("Serious exception occured with UserID ",self.UserID," Error",e) print("Process will now exit") def Login(self,Arguments): @@ -469,8 +582,10 @@ def Exit(self,Arguments = None): class MonitorConnection: - def __init__(self,Connection): + def __init__(self,Thread_Name,Thread_Queue,Connection): self.DB = AATC_DB.DBConnection() + self.Thread_Name = Thread_Name + self.Thread_Queue = Thread_Queue self.con = Connection self.Crypto = AATC_Crypto.Crypter(self.con, mode = "SERVER") self.MonitorID = -1 #Used to identify if has logged in yet @@ -496,27 +611,23 @@ def Connection_Loop(self): Arguments may be converted from Tuple to Dict in future for clarity """ - try: - while self.MonitorID == -1:#Repeats until logs in + Exit = False + while not Exit: + try: data = self.Recv() - try: - Command,Arguments = data[0],data[1] + Command,Arguments = data[0],data[1] + if self.MonitorID == -1: if Command == "Login": Sucess,Message,Data = self.Login(Arguments) elif Command == "AddMonitor": # If adding a new Monitor, one must create it first, then log in seperatly Sucess,Message,Data = self.AddMonitor(Arguments) + elif Command == "Exit": + Sucess,Message,Data = self.Exit(Arguments) + Exit = True else: Sucess,Message,Data = False,"Command does not exist",[] - except Exception as e: - Sucess,Message,Data = False,"An Error occured"+str(e),[] - print("Error occured with MonitorID:",str(self.MonitorID),"Error :",str(e)," Sending failure message") - self.Send((Sucess,Message,Data)) - - Exit = False - while not Exit: - data = self.Recv() - try: - Command,Arguments = data[0],data[1] + + else: if Command == "GetNoFlyZones": Sucess,Message,Data = self.GetNoFlyZones(Arguments) @@ -559,17 +670,98 @@ def Connection_Loop(self): else: Sucess,Message,Data = False,"Command does not exist",[] print("Monitor tried to use unregistered command") - except Exception as e: - Sucess,Message,Data = False,"An Error occured"+str(e),[] - print("Error occured with MonitorID:",str(self.MonitorID),"Error :",str(e)," Sending failure message") - ## print(Message,str(Data)) + except Exception as e: + Sucess,Message,Data = False,"An Error occured"+str(e),[] + print("Error occured with MonitorID:",str(self.MonitorID),"Error :",str(e)," Sending failure message") + try: self.Send((Sucess,Message,Data)) - - except Exception as e: - if type(e) == BrokenPipeError: + except Exception as e: print("MonitorID:",self.MonitorID," disconnected") - else: - print("Serious exception occured with MonitorID ",self.MonitorID," Error",e) + Exit = True + + if not self.Thread_Queue.empty(): + data = Thread_Queue.get() + Command,Arguments = data[0],data[1] + if Command == "Exit": + Exit = True + + + +## try: +## Exit = False +## while self.MonitorID == -1 and not Exit:#Repeats until logs in +## data = self.Recv() +## try: +## Command,Arguments = data[0],data[1] +## if Command == "Login": +## Sucess,Message,Data = self.Login(Arguments) +## elif Command == "AddMonitor": # If adding a new Monitor, one must create it first, then log in seperatly +## Sucess,Message,Data = self.AddMonitor(Arguments) +## else: +## Sucess,Message,Data = False,"Command does not exist",[] +## except Exception as e: +## Sucess,Message,Data = False,"An Error occured"+str(e),[] +## print("Error occured with MonitorID:",str(self.MonitorID),"Error :",str(e)," Sending failure message") +## self.Send((Sucess,Message,Data)) +## +## +## while not Exit: +## data = self.Recv() +## try: +## Command,Arguments = data[0],data[1] +## if Command == "GetNoFlyZones": +## Sucess,Message,Data = self.GetNoFlyZones(Arguments) +## +## elif Command == "GetDronesAll": +## Sucess,Message,Data = self.GetDronesAll(Arguments) +## +## elif Command == "GetUserID": +## Sucess,Message,Data = self.GetUserID(Arguments) +## elif Command == "GetUsername": +## Sucess,Message,Data = self.GetUsername(Arguments) +## +## elif Command == "GetMonitorDrones": +## Sucess,Message,Data = self.GetMonitorDrones(Arguments) +## elif Command == "GetMonitorFlights": +## Sucess,Message,Data = self.GetMonitorFlights(Arguments) +## elif Command == "GetMonitorFlightWaypoints": +## Sucess,Message,Data = self.GetMonitorFlightWaypoints(Arguments) +## +## elif Command == "GetMonitorID": +## Sucess,Message,Data = self.GetMonitorID(Arguments) +## elif Command == "GetMonitorName": +## Sucess,Message,Data = self.GetMonitorName(Arguments) +## +## elif Command == "RemoveMonitorPermission": +## Sucess,Message,Data = self.RemoveMonitorPermission(Arguments) +## elif Command == "GetMonitorPermissionMonitor": +## Sucess,Message,Data = self.GetMonitorPermissionMonitor(Arguments) +## +## elif Command == "GetFlightsAll": +## Sucess,Message,Data = self.GetFlightsAll(Arguments) +## +## elif Command == "GetFlightWaypointsAll": +## Sucess,Message,Data = self.GetFlightWaypointsAll(Arguments) +## +## elif Command == "Exit": +## Sucess,Message,Data = self.Exit(Arguments) +## Exit = True +## +## #Else if command doesnt exist send back Failure +## else: +## Sucess,Message,Data = False,"Command does not exist",[] +## print("Monitor tried to use unregistered command") +## except Exception as e: +## Sucess,Message,Data = False,"An Error occured"+str(e),[] +## print("Error occured with MonitorID:",str(self.MonitorID),"Error :",str(e)," Sending failure message") +## ## print(Message,str(Data)) +## self.Send((Sucess,Message,Data)) +## +## except Exception as e: +## if type(e) == BrokenPipeError: +## print("MonitorID:",self.MonitorID," disconnected") +## else: +## print("Serious exception occured with MonitorID ",self.MonitorID," Error",e) print("Process is exiting") ################################ @@ -662,8 +854,10 @@ def Exit(self,Arguments = None): class DroneConnection: - def __init__(self,Connection): + def __init__(self,Thread_Name,Thread_Queue,Connection): self.DB = AATC_DB.DBConnection() + self.Thread_Name = Thread_Name + self.Thread_Queue = Thread_Queue self.con = Connection self.Crypto = AATC_Crypto.Crypter(self.con, mode = "SERVER") self.DroneID = -1 #Used to identify if has logged in yet @@ -690,26 +884,21 @@ def Connection_Loop(self): Arguments may be converted from Tuple to Dict in future for clarity """ - try: - while self.DroneID == -1:#Repeats until logs in + Exit = False + while not Exit: + try: data = self.Recv() - try: - Command,Arguments = data[0],data[1] + Command,Arguments = data[0],data[1] + if self.DroneID == -1: if Command == "Login": Sucess,Message,Data = self.Login(Arguments) - + elif Command == "Exit": + Sucess,Message,Data = self.Exit(Arguments) + Exit = True else: Sucess,Message,Data = False,"Command does not exist",[] - except Exception as e: - Sucess,Message,Data = False,"An Error occured"+str(e),[] - print("Error occured with DroneID:",str(self.DroneID),"Error :",str(e)," Sending failure message") - self.Send((Sucess,Message,Data)) - - Exit = False - while not Exit: - data = self.Recv() - try: - Command,Arguments = data[0],data[1] + + else: if Command == "UpdateDroneStatus": Sucess,Message,Data = self.UpdateDroneStatus(Arguments) @@ -727,23 +916,85 @@ def Connection_Loop(self): elif Command == "Exit": Sucess,Message,Data = self.Exit(Arguments) + Exit = True #Else if command doesnt exist send back Failure else: Sucess,Message,Data = False,"Command does not exist",[] print("Drone tried to use unregistered command") - except Exception as e: - if type(e) != TypeError:# if this error type occurs connection has failed and would otherwise flood console with irrelevant errors - print("Error occured with DroneID:",str(self.DroneID),"Error :",str(e)," Sending failure message") - Sucess,Message,Data = False,"An Error occured"+str(e),[] - + + except Exception as e: + Sucess,Message,Data = False,"An Error occured"+str(e),[] + print("Error occured with DroneID:",str(self.DroneID),"Error :",str(e)," Sending failure message") + try: self.Send((Sucess,Message,Data)) - - except Exception as e: - if type(e) == BrokenPipeError: + except Exception as e: print("DroneID:",self.DroneID," disconnected") - else: - print("Serious exception occured with DroneID ",self.DroneID," Error",e) + Exit = True + + if not self.Thread_Queue.empty(): + data = Thread_Queue.get() + Command,Arguments = data[0],data[1] + if Command == "Exit": + Exit = True + + + +## try: +## Exit = False +## while self.DroneID == -1 and not Exit:#Repeats until logs in +## data = self.Recv() +## try: +## Command,Arguments = data[0],data[1] +## if Command == "Login": +## Sucess,Message,Data = self.Login(Arguments) +## +## else: +## Sucess,Message,Data = False,"Command does not exist",[] +## except Exception as e: +## Sucess,Message,Data = False,"An Error occured"+str(e),[] +## print("Error occured with DroneID:",str(self.DroneID),"Error :",str(e)," Sending failure message") +## self.Send((Sucess,Message,Data)) +## +## +## while not Exit: +## data = self.Recv() +## try: +## Command,Arguments = data[0],data[1] +## if Command == "UpdateDroneStatus": +## Sucess,Message,Data = self.UpdateDroneStatus(Arguments) +## +## elif Command == "DroneGetDroneInfo": +## Sucess,Message,Data = self.DroneGetDroneInfo(Arguments) +## +## elif Command == "CheckForFlight": +## Sucess,Message,Data = self.CheckForFlight(Arguments) +## elif Command == "GetFlight": +## Sucess,Message,Data = self.GetFlight(Arguments) +## elif Command == "GetFlightWaypoints": +## Sucess,Message,Data = self.GetFlightWaypoints(Arguments) +## elif Command == "MarkFlightComplete": +## Sucess,Message,Data = self.MarkFlightComplete(Arguments) +## +## elif Command == "Exit": +## Sucess,Message,Data = self.Exit(Arguments) +## +## #Else if command doesnt exist send back Failure +## else: +## Sucess,Message,Data = False,"Command does not exist",[] +## print("Drone tried to use unregistered command") +## except Exception as e: +## if type(e) != TypeError:# if this error type occurs connection has failed and would otherwise flood console with irrelevant errors +## print("Error occured with DroneID:",str(self.DroneID),"Error :",str(e)," Sending failure message") +## Sucess,Message,Data = False,"An Error occured"+str(e),[] +## +## self.Send((Sucess,Message,Data)) +## +## except Exception as e: +## if type(e) == BrokenPipeError: +## print("DroneID:",self.DroneID," disconnected") +## else: +## print("Serious exception occured with DroneID ",self.DroneID," Error",e) print("Process is exiting") def Login(self,Arguments): @@ -798,11 +1049,12 @@ def Exit(self,Arguments = None): -def Cleaner(KillSwitch,Interval = 36000,EndTimeThreshold = 72000): - while not KillSwitch.is_set(): +def Cleaner(Thread_Name,Thread_Queue,Interval = 36000,EndTimeThreshold = 72000): + Exit = False + while not Exit: try: DB = AATC_DB.DBConnection() - while not KillSwitch.is_set(): + while not Exit: print("Cleaner starting cleaning") DB.CleanMonitorPermissions() @@ -813,6 +1065,12 @@ def Cleaner(KillSwitch,Interval = 36000,EndTimeThreshold = 72000): DB.CleanCompletedFlightWaypoints(WrappedID[0]) print("Cleaner completed cleaning. Sleeping..") time.sleep(Interval) + + if not Thread_Queue.empty(): + data = Thread_Queue.get() + Command,Arguments = data[0],data[1] + if Command == "Exit": + Exit = True except Exception as e: print("Error in Cleaner",e) diff --git a/AATC_Server_Starter.py b/AATC_Server_Starter.py index 737525e..a9d60e4 100644 --- a/AATC_Server_Starter.py +++ b/AATC_Server_Starter.py @@ -1,4 +1,4 @@ -import multiprocessing,socket,AATC_NoFlyZoneGrapher,sys,time +import multiprocessing,socket,AATC_NoFlyZoneGrapher,sys,time,AATC_GPIO import AATC_Server_002 as AATC_Server from AATC_Coordinate import * @@ -30,9 +30,12 @@ def UserProcessSpawner(): except Exception as e: print("Error in UserProcessSpawner",str(e)) -def MakeUserConnection(conn): - UConn = AATC_Server.UserConnection(conn) - UConn.Connection_Loop() +def MakeUserConnection(Thread_Name,Thread_Queue,conn): + try: + UConn = AATC_Server.UserConnection(Thread_Name,Thread_Queue,conn) + UConn.Connection_Loop() + except Exception as e: + print("Serious error in UserConnection",e) ##################################################### @@ -62,9 +65,12 @@ def MonitorProcessSpawner(): except Exception as e: print("Error in MonitorProcessSpawner",str(e)) -def MakeMonitorConnection(conn): - MConn = AATC_Server.MonitorConnection(conn) - MConn.Connection_Loop() +def MakeMonitorConnection(Thread_Name,Thread_Queue,conn): + try: + MConn = AATC_Server.MonitorConnection(Thread_Name,Thread_Queue,conn) + MConn.Connection_Loop() + except Exception as e: + print("Serious error in MonitorConnection",e) @@ -98,9 +104,12 @@ def DroneProcessSpawner(): except Exception as e: print("Error in DroneProcessSpawner",str(e)) -def MakeDroneConnection(conn): - DConn = AATC_Server.DroneConnection(conn) - DConn.Connection_Loop() +def MakeDroneConnection(Thread_Name,Thread_Queue,conn): + try: + DConn = AATC_Server.DroneConnection(Thread_Name,Thread_Queue,conn) + DConn.Connection_Loop() + except Exception as e: + print("Serious error in DroneConnection",e) @@ -108,67 +117,106 @@ def MakeDroneConnection(conn): ########################################################## -def ProcessSpawner(Port,Type,Target,KillSwitch): - ProcessList = [] - while not KillSwitch.is_set(): +def ProcessSpawner(Name,Communications_Queue,Port,Type,Target): + Exit = False + Spawner_Control_Queue = AATC_GPIO.Create_Controller() + ID_Counter = 1 + DisplayName = "["+str(Name)+":"+str(Type)+"]" + while not Exit: try: HOST = '' PORT = Port s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - print( 'Socket created') + print(DisplayName,'Socket created') s.bind((HOST, PORT)) - print( 'Socket bind complete') + print(DisplayName, 'Socket bind complete') s.listen(10) - print( 'Socket now listening') + print(DisplayName, 'Socket now listening') - while not KillSwitch.is_set(): + while not Exit: try: conn, addr = s.accept() - print( '\nConnected with ' + addr[0] + ':' + str(addr[1])+ "Type:"+Type) - Process = multiprocessing.Process(target = Target, args = (conn,)) - Process.start() - ProcessList.append(Process) + print(DisplayName, ' Connected with' , addr[0] , ':' , str(addr[1]), "Type:",Type) + Thread_Name = Type+str(ID_Counter) + Spawner_Control_Queue.put(("Controller","Create_Process",(Thread_Name,Target,(conn,)))) + ID_Counter +=1 except Exception as e: print("Error creating" ,Type,"connection",str(e)) + + #Check for commands from Communications_Queue + if not Communications_Queue.empty(): + data = Communications_Queue.get() + Command,Arguments = data[0],data[1] + if Command == "Exit": + self.Exit = True + + except Exception as e: print("Error in",Type,"Process Spawner",str(e)) - for Process in ProcessList: - Process.join() + + Spawner_Control_Queue.put(("Controller","Exit",(True,))) + +def StartProcesses(Control_Queue): + Control_Queue.put(("Controller","Create_Process",("USpawner",ProcessSpawner,(8000,"User",MakeUserConnection)))) + + Control_Queue.put(("Controller","Create_Process",("MSpawner",ProcessSpawner,(8001,"Monitor",MakeMonitorConnection)))) + + Control_Queue.put(("Controller","Create_Process",("DSpawner",ProcessSpawner,(8002,"Drone",MakeDroneConnection)))) + + + Control_Queue.put(("Controller","Create_Process",("Grapher",AATC_NoFlyZoneGrapher.NoFlyZoneGrapher))) + Control_Queue.put(("Controller","Create_Process",("Cleaner",AATC_Server.Cleaner))) + + print("[StartProcesses] All processes started") if __name__ == "__main__": print("Server is starting") - KillSwitch = multiprocessing.Event() - HighProcessList = [] - #Launch UserProcess spawner - UPS = multiprocessing.Process(target = ProcessSpawner,args = (8000,"User",MakeUserConnection,KillSwitch)) - HighProcessList.append(UPS) - UPS.start() - - #Launch MonitorPerocess spawner - MPS = multiprocessing.Process(target = ProcessSpawner,args = (8001,"Monitor",MakeMonitorConnection,KillSwitch)) - HighProcessList.append(MPS) - MPS.start() - - #Launch DroneProcess Spawner - DPS = multiprocessing.Process(target = ProcessSpawner,args = (8002,"Drone",MakeDroneConnection,KillSwitch)) - HighProcessList.append(DPS) - DPS.start() +## KillSwitch = multiprocessing.Event() +## HighProcessList = [] +## #Launch UserProcess spawner +## UPS = multiprocessing.Process(target = ProcessSpawner,args = (8000,"User",MakeUserConnection,KillSwitch)) +## HighProcessList.append(UPS) +## UPS.start() +## +## #Launch MonitorPerocess spawner +## MPS = multiprocessing.Process(target = ProcessSpawner,args = (8001,"Monitor",MakeMonitorConnection,KillSwitch)) +## HighProcessList.append(MPS) +## MPS.start() +## +## #Launch DroneProcess Spawner +## DPS = multiprocessing.Process(target = ProcessSpawner,args = (8002,"Drone",MakeDroneConnection,KillSwitch)) +## HighProcessList.append(DPS) +## DPS.start() +## +## #Launch NoFlyZoneGrapher +## NFZG = multiprocessing.Process(target = AATC_NoFlyZoneGrapher.NoFlyZoneGrapher, args = (KillSwitch,)) +## HighProcessList.append(NFZG) +## NFZG.start() +## +## CLN = multiprocessing.Process(target = AATC_Server.Cleaner,args = (KillSwitch,)) +## HighProcessList.append(CLN) +## CLN.start() - #Launch NoFlyZoneGrapher - NFZG = multiprocessing.Process(target = AATC_NoFlyZoneGrapher.NoFlyZoneGrapher, args = (KillSwitch,150)) - HighProcessList.append(NFZG) - NFZG.start() - CLN = multiprocessing.Process(target = AATC_Server.Cleaner,args = (KillSwitch,150)) - HighProcessList.append(CLN) - CLN.start() + Control_Queue = AATC_GPIO.Create_Controller() + StartProcesses(Control_Queue) + + + + + + + + + + Main_Command = "" while Main_Command != "EXIT": Main_Command = input("Enter main command >>").upper() @@ -177,10 +225,9 @@ def ProcessSpawner(Port,Type,Target,KillSwitch): print("Killing all Server processes....") print("This may take time, sleeping processes will be killed when resuming from sleep") - KillSwitch.set() - for Process in HighProcessList: - Process.join() - print("Process:",Process,"has exited") + + Control_Queue.put(("Controller","Exit",(True,))) + print("Main process is now exiting...") sys.exit()