diff --git a/FreeTAKServer.egg-info/PKG-INFO b/FreeTAKServer.egg-info/PKG-INFO new file mode 100644 index 00000000..319952ce --- /dev/null +++ b/FreeTAKServer.egg-info/PKG-INFO @@ -0,0 +1,184 @@ +Metadata-Version: 2.1 +Name: FreeTAKServer +Version: 0.112 +Summary: An open source server for the TAK family of applications. +Home-page: https://github.com/Tapawingo/FreeTakServer +Author: Ghosty 1008 +Author-email: your.email@domain.com +License: MIT +Download-URL: https://github.com/Tapawingo/FreeTakServer/archive/v0.8.4-Beta.tar.gz +Description: # FreeTAKServer + + ![the Parrot is not dead](https://github.com/Tapawingo/FreeTakServer/blob/master/docs/FreeTakServer%20specs/FreeTakServerLogo.png?raw=true) + + Welcome to the FreeTakServer (FTS) git repository. + + FTS is a Python3 implementation of the TAK Server for devices like CivTAK , WinTAK and ITAK, it is cross-platform and is only dependent on python stdlib libraries. We use the Flask framework for web services. + it's free and open source (released under the Eclipse Public License). + + ## Use cases + FTS allows you to connect ATAK clients to share geo information, to chat with all the connected clients, exchange files and more. + It intends to support all the major use cases of the original TAK server. + ![the domain model with all the know objects used by CIVTAK/ wintak](https://github.com/Tapawingo/TAKlib/blob/master/docs/FreeTakServer%20specs/FreeTak%20Use%20Case%20model.png?raw=true) + + ## Community + This code is currently in *BETA STAGE* + Check out our roadmap @ FreeTakServer#25 to see what is planned + If you have any issues don't hesitate to bring it up https://github.com/Tapawingo/FreeTakServer/issues, as TAKFreeServer is still in development. + + ### Donate back + the FTS team is working daily on the development of a open and free solution. We plan to do more that simply replicate the functionalities of the legacy TAK server, our road map includes integration with open source systems like LORA's Meshtastic, porting it to Android, having an open API and much more. + + We are doing it for free because we believe that donating personal time to a cause its a endeavour that is worthy per-se, However, a part time, we are also spending our own money to: + - Maintain a Public server and a test server + - Investing in different technologies for R&D + + if you feel that FTS is useful to you and you can donate in those challenging times please consider to send you contribution here: + [DONATE](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=brothercorvo%40gmail.com&item_name=FreeTAKServer+R%26D¤cy_code=CAD&source=url) + + You can also support the project by buying one of our [t-shirts](http://tee.pub/lic/elARpZYCmaw) + + NOTE: + not a big fan of Paypal, but that is the easier way I found for an initial attempt. We may go to some more ethical system in future. + + ### Public instance + we support a [public instance}(https://www.reddit.com/r/ATAK/wiki/index/freetakserver) of FTS. + - download the configuration {here}(https://drive.google.com/open?id=1IK1LfPN13EWikHaMyOuDDwIerNGz-Wl) + - use the Import manager in ATAK to import the configuration + + ### Tell us what you think! + to discuss with the developer team + Use the reddit server + https://www.reddit.com/r/ATAK/ + and the Discord chat + https://discordapp.com/invite/XEPyhHA + + ## Architecture + TAKFreeServer uses a MVC pattern, the concept of a COT is described in a set of Domain classes, generated from the UML model using a Model Driven Architecture approach. + ![the domain model with all the know objects used by CIVTAK/ wintak](https://github.com/FreeTAKTeam/FreeTakServer/blob/master/docs/FreeTAKServer%20Model.png) + YOu can see the complete COT description {here}(https://github.com/FreeTAKTeam/FreeTakServer/blob/master/docs/FreeTakServer%20specs/COTDomainModel.pdf) + + ## Documentation + under docs, you can find various documents including an UML model of the Domain classes involved in a COT event. + + ## Requirements + - Python 3.6 (or better) + + ## Installing and using FreeTakServer + Important Note: depending from the system you are using, the following commands may be executed using python3, Pip3 or in alternative python, Pip (without the 3). + + + ### Prerequisites + you will need to install Python 3, PIP before you can install FTS + + - Install Python3 + ``` + sudo apt update && sudo apt install python3 && sudo apt install pip3` (Ubuntu)``` + ``` + ### install FreeTakServer + Since version 0.8, FTS supports Pip installation, manual installation can be done with some modifications of the import paths, however we don't support it + + ``` + sudo python -m pip install FreeTAKServer + ``` + + Optional: check if installation is correctly executed and install any missing packages if prompted + ``` + sudo python -m pip check FreeTakServer + ``` + + note under windows it's installed under + ``` + C:\Users\user.name\AppData\Local\Programs\Python\PythonXX\Lib\site-packages + ``` + + ## Run FreeTakServer + + ### Linux + + #### Run Server in console + + ``` + sudo python3 -m FreeTAKServer.controllers.services.FTS -DataPackageIP [YourIP] + ``` + this will start the server with Port 8087 and API port 8080 on the IP defined in [yourIP] + + other parameters you can use: + -AutoStart: (weather the full server start or just the RestAPI, must be True or False) + -CoTIP [yourIP] + -DataPackageIP[yourIP] : set the IP where CoTs are send + -CoTPort [aPort] : the port you want clients to connect to + -DataPackagePort [anotherPort]: the port you want datapackages to be sent and received on + + if you dont set any of the above, FTS will adopt a "Convention instead of Configuration" approach and try to set all from the configuation file + + Open a new console in a separate window + run FTS Command Line Interface with + ``` + python -m FreeTAKServer.views.CLI + ``` + + to get a list of other supported commands type + + ```help``` + + #### Run Server as Demon + use this command to run FTS independently from your command window. + + ``` + sudo nohup python3 -m FreeTAKServer.controllers.FTS -DataPackageIP [YourIP] & + ``` + + ### Windows + go to the start menu and type cmd to start a command prompt + open a console with admin rights + ``` + python3 -m FreeTAKServer.controllers.FTS -DataPackageIP [YourIP] + ``` + + ### Troubleshooting + if, trying to start FTS you get an error 'package not found' + ``` + 'package not found' + ``` + navigate to the physical location where the controllers are installed and start the server from there + + ## Update FreeTakServer + if you already installed FTS with pip you can use + ``` + pip install FreeTAKServer --upgrade + ``` + + + ### client2client datapackages + + If you have issues sending datapackages directly to clients via FTS, make sure -IP you specified can be reached from your device. + A quick way to test if it works is to take a picture with Quick Pic in ATAK and send it to another client. Please also note that for that test ATAK clients needs to be on different network (ie one on mobile and one on wifi), because if you run them in same network (wifi, vpn, etc) they will just use same multicast group, bypassing FTS completely. + When you post package to specific contact in ATAK, following happens: + + 1) Datapackage is uploaded to server, recorded in database and stored in FTS directory + 2) Client receives payload with URL pointing to datapackage so ATAK can download it + + Assuming you want to run open-to-everyone FTS instance, and you have server hosted somewhere, you need to specify _public_ IP address in -IP argument. And just in case, -IP also accepts domain names. + If you run it at home and port forward on router doesn't work, check if you receive actual IP address and not being NATed and ports 8080 and 8087 are not filtered - you can ask your ISP about that. + + + + ## Project Structure + - TakFreeServer + - **Controllers**: Contains all the business Logic + - **Models**: Contains all the COT object model + - **TAKLinuxService**: a demon for linux OS + - **TakWinService**: a service for the windows OS + - Docs: Usefull documentation regarding COTS and different logs to understand how those are implemented + - Model: a UML model in Sparx EnterpriseArchitect format (see https://sparxsystems.com/products/ea/trial/request.html). + - Old: Legacy versions + +Keywords: TAK,OPENSOURCE +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Topic :: Software Development :: Build Tools +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python :: 3.6 +Description-Content-Type: text/markdown diff --git a/FreeTAKServer.egg-info/SOURCES.txt b/FreeTAKServer.egg-info/SOURCES.txt new file mode 100644 index 00000000..89c61684 --- /dev/null +++ b/FreeTAKServer.egg-info/SOURCES.txt @@ -0,0 +1,212 @@ +README.md +setup.cfg +setup.py +FreeTAKServer/__init__.py +FreeTAKServer.egg-info/PKG-INFO +FreeTAKServer.egg-info/SOURCES.txt +FreeTAKServer.egg-info/dependency_links.txt +FreeTAKServer.egg-info/requires.txt +FreeTAKServer.egg-info/top_level.txt +FreeTAKServer/controllers/ActiveThreadsController.py +FreeTAKServer/controllers/AddDataToCoTList.py +FreeTAKServer/controllers/ApplyFullJsonController.py +FreeTAKServer/controllers/AsciiController.py +FreeTAKServer/controllers/BasicModelInstantiate.py +FreeTAKServer/controllers/ClientInformationController.py +FreeTAKServer/controllers/ClientInformationQueueController.py +FreeTAKServer/controllers/ClientReceptionHandler.py +FreeTAKServer/controllers/ClientSendHandler.py +FreeTAKServer/controllers/CoTTypeController.py +FreeTAKServer/controllers/CreateLoggerController.py +FreeTAKServer/controllers/CreateStartupFilesController.py +FreeTAKServer/controllers/DataQueueController.py +FreeTAKServer/controllers/FilterGroupController.py +FreeTAKServer/controllers/HealthCheckController.py +FreeTAKServer/controllers/MainSocketController.py +FreeTAKServer/controllers/MessageTypeController.py +FreeTAKServer/controllers/ProcessDataController.py +FreeTAKServer/controllers/ReceiveConnections.py +FreeTAKServer/controllers/ReceiveConnectionsProcessController.py +FreeTAKServer/controllers/SendClientData.py +FreeTAKServer/controllers/SendDataController.py +FreeTAKServer/controllers/TCPSocketController.py +FreeTAKServer/controllers/XMLCoTController.py +FreeTAKServer/controllers/__init__.py +FreeTAKServer/controllers/clientInterfaceController.py +FreeTAKServer/controllers/statusCheck.py +FreeTAKServer/controllers/userInterfaceController.py +FreeTAKServer/controllers/DatabaseControllers/DataPackageTableController.py +FreeTAKServer/controllers/DatabaseControllers/DatabaseController.py +FreeTAKServer/controllers/DatabaseControllers/EventTableController.py +FreeTAKServer/controllers/DatabaseControllers/RootController.py +FreeTAKServer/controllers/DatabaseControllers/TableController.py +FreeTAKServer/controllers/DatabaseControllers/UserTableController.py +FreeTAKServer/controllers/DatabaseControllers/VideoStreamTableController.py +FreeTAKServer/controllers/DatabaseControllers/__init__.py +FreeTAKServer/controllers/SpecificCoTControllers/SendCoTAbstractController.py +FreeTAKServer/controllers/SpecificCoTControllers/SendDisconnectController.py +FreeTAKServer/controllers/SpecificCoTControllers/SendDropPointController.py +FreeTAKServer/controllers/SpecificCoTControllers/SendEmergencyController.py +FreeTAKServer/controllers/SpecificCoTControllers/SendGeoChatController.py +FreeTAKServer/controllers/SpecificCoTControllers/SendHealthCheckController.py +FreeTAKServer/controllers/SpecificCoTControllers/SendInvalidCoTController.py +FreeTAKServer/controllers/SpecificCoTControllers/SendOtherController.py +FreeTAKServer/controllers/SpecificCoTControllers/SendPingController.py +FreeTAKServer/controllers/SpecificCoTControllers/SendTakPongController.py +FreeTAKServer/controllers/SpecificCoTControllers/SendUserUpdateController.py +FreeTAKServer/controllers/SpecificCoTControllers/__init__.py +FreeTAKServer/controllers/configuration/ArgumentConstants.py +FreeTAKServer/controllers/configuration/ClientReceptionHandlerConstants.py +FreeTAKServer/controllers/configuration/ClientReceptionLoggingConstants.py +FreeTAKServer/controllers/configuration/DataPackageServerConstants.py +FreeTAKServer/controllers/configuration/DatabaseConfiguration.py +FreeTAKServer/controllers/configuration/LoggingConstants.py +FreeTAKServer/controllers/configuration/MainConfig.py +FreeTAKServer/controllers/configuration/OrchestratorConstants.py +FreeTAKServer/controllers/configuration/ReceiveConnectionsConstants.py +FreeTAKServer/controllers/configuration/RestAPIVariables.py +FreeTAKServer/controllers/configuration/SQLcommands.py +FreeTAKServer/controllers/configuration/__init__.py +FreeTAKServer/controllers/logs/__init__.py +FreeTAKServer/controllers/services/DataPackageServer.py +FreeTAKServer/controllers/services/FTS.py +FreeTAKServer/controllers/services/Orchestrator.py +FreeTAKServer/controllers/services/RestAPI.py +FreeTAKServer/controllers/services/TCPCoTServiceController.py +FreeTAKServer/controllers/services/__init__.py +FreeTAKServer/model/ActiveThreads.py +FreeTAKServer/model/ClientInformation.py +FreeTAKServer/model/ClientInformationQueue.py +FreeTAKServer/model/DataQueue.py +FreeTAKServer/model/DestList.py +FreeTAKServer/model/FilterGroup.py +FreeTAKServer/model/RawCoT.py +FreeTAKServer/model/RawConnectionInformation.py +FreeTAKServer/model/ReceiveConnectionsProcess.py +FreeTAKServer/model/SimpleClient.py +FreeTAKServer/model/SimpleClientVariables.py +FreeTAKServer/model/__init__.py +FreeTAKServer/model/detailObject.py +FreeTAKServer/model/socketInformation.py +FreeTAKServer/model/FTSModel/Archive.py +FreeTAKServer/model/FTSModel/Chat.py +FreeTAKServer/model/FTSModel/Chatgrp.py +FreeTAKServer/model/FTSModel/Color.py +FreeTAKServer/model/FTSModel/Contact.py +FreeTAKServer/model/FTSModel/Dest.py +FreeTAKServer/model/FTSModel/Detail.py +FreeTAKServer/model/FTSModel/DimensionTypes.py +FreeTAKServer/model/FTSModel/Emergency.py +FreeTAKServer/model/FTSModel/EntityTypes.py +FreeTAKServer/model/FTSModel/Event.py +FreeTAKServer/model/FTSModel/Group.py +FreeTAKServer/model/FTSModel/Hierarchy.py +FreeTAKServer/model/FTSModel/IdentityTypes.py +FreeTAKServer/model/FTSModel/Link.py +FreeTAKServer/model/FTSModel/Marti.py +FreeTAKServer/model/FTSModel/Mission.py +FreeTAKServer/model/FTSModel/Point.py +FreeTAKServer/model/FTSModel/Precisionlocation.py +FreeTAKServer/model/FTSModel/Remarks.py +FreeTAKServer/model/FTSModel/Serverdestination.py +FreeTAKServer/model/FTSModel/Status.py +FreeTAKServer/model/FTSModel/Summary.py +FreeTAKServer/model/FTSModel/Takv.py +FreeTAKServer/model/FTSModel/Track.py +FreeTAKServer/model/FTSModel/Uid.py +FreeTAKServer/model/FTSModel/Usericon.py +FreeTAKServer/model/FTSModel/_Group.py +FreeTAKServer/model/FTSModel/__init__.py +FreeTAKServer/model/FTSModel/_medevac_ .py +FreeTAKServer/model/FTSModelVariables/ChatVariables.py +FreeTAKServer/model/FTSModelVariables/ChatgrpVariables.py +FreeTAKServer/model/FTSModelVariables/ColorVariables.py +FreeTAKServer/model/FTSModelVariables/ContactVariables.py +FreeTAKServer/model/FTSModelVariables/DestVariables.py +FreeTAKServer/model/FTSModelVariables/DetailVariables.py +FreeTAKServer/model/FTSModelVariables/EmergencyVariables.py +FreeTAKServer/model/FTSModelVariables/EventVariables.py +FreeTAKServer/model/FTSModelVariables/LinkVariables.py +FreeTAKServer/model/FTSModelVariables/MartiVariables.py +FreeTAKServer/model/FTSModelVariables/PointVariables.py +FreeTAKServer/model/FTSModelVariables/PrecisionlocationVariables.py +FreeTAKServer/model/FTSModelVariables/RemarksVariables.py +FreeTAKServer/model/FTSModelVariables/ServerdestinationVariables.py +FreeTAKServer/model/FTSModelVariables/SummaryVariables.py +FreeTAKServer/model/FTSModelVariables/TakvVariables.py +FreeTAKServer/model/FTSModelVariables/TrackVariables.py +FreeTAKServer/model/FTSModelVariables/UidVariables.py +FreeTAKServer/model/FTSModelVariables/UsericonVariables.py +FreeTAKServer/model/FTSModelVariables/_GroupVariables.py +FreeTAKServer/model/FTSModelVariables/__init__.py +FreeTAKServer/model/FTSModelVariables/statusVariables.py +FreeTAKServer/model/SQLAlchemy/DataPackage.py +FreeTAKServer/model/SQLAlchemy/Event.py +FreeTAKServer/model/SQLAlchemy/Root.py +FreeTAKServer/model/SQLAlchemy/User.py +FreeTAKServer/model/SQLAlchemy/UserConfiguration.py +FreeTAKServer/model/SQLAlchemy/VideoStream.py +FreeTAKServer/model/SQLAlchemy/__init__.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Archive.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Chat.py +FreeTAKServer/model/SQLAlchemy/CoTTables/CoTTableAbstract.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Color.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Contact.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Dest.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Detail.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Emergency.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Link.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Marti.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Point.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Precisionlocation.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Remarks.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Serverdestination.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Status.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Summary.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Takv.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Track.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Uid.py +FreeTAKServer/model/SQLAlchemy/CoTTables/Usericon.py +FreeTAKServer/model/SQLAlchemy/CoTTables/_Group.py +FreeTAKServer/model/SQLAlchemy/CoTTables/__init__.py +FreeTAKServer/model/ServiceObjects/CoTService.py +FreeTAKServer/model/ServiceObjects/CoTServiceVariables.py +FreeTAKServer/model/ServiceObjects/DataPackageService.py +FreeTAKServer/model/ServiceObjects/DataPackageServiceVariables.py +FreeTAKServer/model/ServiceObjects/FTS.py +FreeTAKServer/model/ServiceObjects/FTSVariables.py +FreeTAKServer/model/ServiceObjects/RestAPIService.py +FreeTAKServer/model/ServiceObjects/RestAPIServiceVariables.py +FreeTAKServer/model/ServiceObjects/__init__.py +FreeTAKServer/model/SpecificCoT/SendDisconnect.py +FreeTAKServer/model/SpecificCoT/SendDropPoint.py +FreeTAKServer/model/SpecificCoT/SendEmergency.py +FreeTAKServer/model/SpecificCoT/SendFederatedCoT.py +FreeTAKServer/model/SpecificCoT/SendGeoChat.py +FreeTAKServer/model/SpecificCoT/SendHealthCheck.py +FreeTAKServer/model/SpecificCoT/SendInvalidCoT.py +FreeTAKServer/model/SpecificCoT/SendOther.py +FreeTAKServer/model/SpecificCoT/SendPing.py +FreeTAKServer/model/SpecificCoT/SendTakPong.py +FreeTAKServer/model/SpecificCoT/SendUserUpdate.py +FreeTAKServer/model/SpecificCoT/SpecificCoTAbstract.py +FreeTAKServer/model/SpecificCoT/__init__.py +FreeTAKServer/model/protobuf/__init__.py +FreeTAKServer/model/protobufModel/__init__.py +FreeTAKServer/model/protobufModel/contact_pb2.py +FreeTAKServer/model/protobufModel/cotevent_pb2.py +FreeTAKServer/model/protobufModel/detail_pb2.py +FreeTAKServer/model/protobufModel/fig_pb2.py +FreeTAKServer/model/protobufModel/group_pb2.py +FreeTAKServer/model/protobufModel/precisionlocation_pb2.py +FreeTAKServer/model/protobufModel/simple_pb2.py +FreeTAKServer/model/protobufModel/status_pb2.py +FreeTAKServer/model/protobufModel/takcontrol_pb2.py +FreeTAKServer/model/protobufModel/takmessage_pb2.py +FreeTAKServer/model/protobufModel/takv_pb2.py +FreeTAKServer/model/protobufModel/track_pb2.py +FreeTAKServer/model/sockets/MainSocket.py +FreeTAKServer/model/sockets/TCPServerSocket.py +FreeTAKServer/model/sockets/__init__.py +FreeTAKServer/views/CLI.py +FreeTAKServer/views/__init__.py \ No newline at end of file diff --git a/FreeTAKServer.egg-info/dependency_links.txt b/FreeTAKServer.egg-info/dependency_links.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/FreeTAKServer.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/FreeTAKServer.egg-info/requires.txt b/FreeTAKServer.egg-info/requires.txt new file mode 100644 index 00000000..cb2d1f28 --- /dev/null +++ b/FreeTAKServer.egg-info/requires.txt @@ -0,0 +1,6 @@ +flask +lxml +pathlib +tabulate +sqlalchemy +setuptools diff --git a/FreeTAKServer.egg-info/top_level.txt b/FreeTAKServer.egg-info/top_level.txt new file mode 100644 index 00000000..8467b14f --- /dev/null +++ b/FreeTAKServer.egg-info/top_level.txt @@ -0,0 +1 @@ +FreeTAKServer diff --git a/FreeTAKServer/.gitignore b/FreeTAKServer/.gitignore new file mode 100644 index 00000000..a069ef62 --- /dev/null +++ b/FreeTAKServer/.gitignore @@ -0,0 +1,3 @@ +controllers/logs/FTS_debug.log +controllers/logs/FTS_info.log +controllers/logs/FTS_http.log \ No newline at end of file diff --git a/FreeTAKServer/__init__.py b/FreeTAKServer/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/controllers/ActiveThreadsController.py b/FreeTAKServer/controllers/ActiveThreadsController.py index 992c0e12..68438f40 100644 --- a/FreeTAKServer/controllers/ActiveThreadsController.py +++ b/FreeTAKServer/controllers/ActiveThreadsController.py @@ -7,7 +7,7 @@ # Original author: Natha Paquette # ####################################################### -from FreeTAKServer.controllers.model.ActiveThreads import ActiveThreads +from FreeTAKServer.model.ActiveThreads import ActiveThreads class ActiveThreadsController: def __init__(self): diff --git a/FreeTAKServer/controllers/AddDataToCoTList.py b/FreeTAKServer/controllers/AddDataToCoTList.py new file mode 100644 index 00000000..7f78749c --- /dev/null +++ b/FreeTAKServer/controllers/AddDataToCoTList.py @@ -0,0 +1,27 @@ +import multiprocessing + +class AddDataToCoTList: + def __init__(self): + pass + + #this function sends specified data to all pipes within a provided array + def send(self, pipes, data): + for pipe in pipes: + try: + pipe.send(data) + except Exception as e: + print(e) + pass + return 1 + + #this function attempts to receive data from a specified pipe and then return the data + def recv(self, pipe): + try: + out = pipe.poll(timeout=0.1) + if out: + data = pipe.recv() + return data + else: + return 0 + except Exception as e: + print(e) \ No newline at end of file diff --git a/FreeTAKServer/controllers/ApplyFullJsonController.py b/FreeTAKServer/controllers/ApplyFullJsonController.py index fb68033d..3bc4d119 100644 --- a/FreeTAKServer/controllers/ApplyFullJsonController.py +++ b/FreeTAKServer/controllers/ApplyFullJsonController.py @@ -1,5 +1,5 @@ -from FreeTAKServer.controllers.model.Event import Event -import json as jsonend + +from FreeTAKServer.model.FTSModel.Event import Event from lxml import etree class ApplyFullJsonController: diff --git a/FreeTAKServer/controllers/BasicModelInstantiate.py b/FreeTAKServer/controllers/BasicModelInstantiate.py index 68d2ce5d..17c19db1 100644 --- a/FreeTAKServer/controllers/BasicModelInstantiate.py +++ b/FreeTAKServer/controllers/BasicModelInstantiate.py @@ -1,5 +1,5 @@ import xml.etree.ElementTree as etree -from FreeTAKServer.controllers.model.Event import Event + class BasicModelInstantiate: def __init__(self, root, modelObject): diff --git a/FreeTAKServer/controllers/ClientInformationController.py b/FreeTAKServer/controllers/ClientInformationController.py index aed823f1..194b555d 100644 --- a/FreeTAKServer/controllers/ClientInformationController.py +++ b/FreeTAKServer/controllers/ClientInformationController.py @@ -4,20 +4,15 @@ # Python implementation of the Class ClientInformationController # Generated by Enterprise Architect # Created on: 19-May-2020 6:56:00 PM -# Original author: Natha Paquette -# +# ####################################################### from lxml import etree -from FreeTAKServer.controllers.model.Event import Event from FreeTAKServer.controllers.BasicModelInstantiate import BasicModelInstantiate import uuid -from logging.handlers import RotatingFileHandler -import logging from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants -import sys from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController -from FreeTAKServer.controllers.model.Event import Event -from FreeTAKServer.controllers.model.ClientInformation import ClientInformation +from FreeTAKServer.model.FTSModel.Event import Event +from FreeTAKServer.model.ClientInformation import ClientInformation from FreeTAKServer.controllers.XMLCoTController import XMLCoTController logger = CreateLoggerController("ClientInformationController").getLogger() @@ -46,48 +41,4 @@ def intstantiateClientInformationModelFromConnection(self, rawClientInformation, return self.clientInformation except Exception as e: logger.error('error in client information controller '+str(e)) - return -1 - - - - - def connectionSetup(self, client, address): - pass - ''' - try: - - sqliteServer = sqlite3.connect(const.DATABASE) - cursor = sqliteServer.cursor() - - first_run = 1 - #create client dictionary within main dictionary containing arrays for data and chat also other stuff for client enitial connection - current_id = 0 - total_clients_connected = 0 - total_clients_connected += 1 - id_data = client.recv(const.STARTBUFFER) - print(id_data) - print('\n'+str(id_data)) - print('\n \n') - tree = ET.fromstring(id_data) - uid = tree.get('uid') - if uid == self.bandaidUID: - return 'Bandaid' - callsign = tree[1][1].attrib['callsign'] - current_id = uuid.uuid1().int - - #add identifying information - self.client_dict[current_id] = {'id_data': '', 'main_data': [], 'alive': 1, 'uid': '', 'client':client, 'callsign':callsign} - self.client_dict[current_id]['id_data'] = id_data - self.client_dict[current_id]['uid'] = uid - cursor.execute(sql.INSERTNEWUSER,(str(current_id), str(uid), str(callsign))) - sqliteServer.commit() - cursor.close() - sqliteServer.close() - #print(self.client_dict) - logger.info('client connected, information is as follows initial'+ '\n'+ 'connection data:'+str(id_data)+'\n'+'current id:'+ str(current_id)) - return str(first_run)+' ? '+str(total_clients_connected)+' ? '+str(id_data)+' ? '+str(current_id) - except Exception as e: - logger.warning('error in connection setup: ' + str(e)) - logger.warning(id_data) - return "error" - ''' \ No newline at end of file + return -1 \ No newline at end of file diff --git a/FreeTAKServer/controllers/ClientInformationQueueController.py b/FreeTAKServer/controllers/ClientInformationQueueController.py index 85cbb1a6..a1da8592 100644 --- a/FreeTAKServer/controllers/ClientInformationQueueController.py +++ b/FreeTAKServer/controllers/ClientInformationQueueController.py @@ -7,7 +7,7 @@ # Original author: Natha Paquette # ####################################################### -from FreeTAKServer.controllers.model.ClientInformationQueue import ClientInformationQueue +from FreeTAKServer.model.ClientInformationQueue import ClientInformationQueue from multiprocessing import Queue class ClientInformationQueueController: diff --git a/FreeTAKServer/controllers/ClientReceptionHandler.py b/FreeTAKServer/controllers/ClientReceptionHandler.py index da9c8c25..9687727b 100644 --- a/FreeTAKServer/controllers/ClientReceptionHandler.py +++ b/FreeTAKServer/controllers/ClientReceptionHandler.py @@ -9,15 +9,6 @@ ####################################################### import time import socket -from xml.dom.minidom import parseString -import threading -import multiprocessing -from FreeTAKServer.controllers.model.socketInformation import socketInformation -from queue import Queue -from logging.handlers import RotatingFileHandler -import logging -import sys -from FreeTAKServer.controllers.configuration.ClientReceptionHandlerConstants import ClientReceptionHandlerConstants from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController from lxml import etree @@ -27,7 +18,6 @@ loggingConstants = ClientReceptionLoggingConstants() -# TODO: add more rigid exception management class ClientReceptionHandler: def __init__(self): @@ -90,7 +80,7 @@ def monitorForData(self, queue): continue else: try: - timeout = time.time() + 0.1 + timeout = time.time() + 1 while time.time() < timeout: try: event = etree.fromstring(part) @@ -134,7 +124,7 @@ def monitorForData(self, queue): def returnReceivedData(self, clientInformation, data, queue): try: - from FreeTAKServer.controllers.model.RawCoT import RawCoT + from FreeTAKServer.model.RawCoT import RawCoT print(data) RawCoT = RawCoT() RawCoT.clientInformation = clientInformation diff --git a/FreeTAKServer/controllers/CoTTypeController.py b/FreeTAKServer/controllers/CoTTypeController.py new file mode 100644 index 00000000..3e02fc4a --- /dev/null +++ b/FreeTAKServer/controllers/CoTTypeController.py @@ -0,0 +1,6 @@ +class CoTTypeController: + def __init__(self): + pass + + def parseType(self, CoT): + return CoT \ No newline at end of file diff --git a/FreeTAKServer/controllers/CreateLoggerController.py b/FreeTAKServer/controllers/CreateLoggerController.py index de6ec569..49002d63 100644 --- a/FreeTAKServer/controllers/CreateLoggerController.py +++ b/FreeTAKServer/controllers/CreateLoggerController.py @@ -1,7 +1,6 @@ from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants from logging.handlers import RotatingFileHandler import logging -import sys import os loggingConstants = LoggingConstants() class CreateLoggerController: diff --git a/FreeTAKServer/controllers/DatabaseControllers/DataPackageTableController.py b/FreeTAKServer/controllers/DatabaseControllers/DataPackageTableController.py new file mode 100644 index 00000000..f14ab5a5 --- /dev/null +++ b/FreeTAKServer/controllers/DatabaseControllers/DataPackageTableController.py @@ -0,0 +1,8 @@ +from FreeTAKServer.controllers.DatabaseControllers.TableController import TableController +from FreeTAKServer.model.SQLAlchemy.DataPackage import DataPackage + + +class DataPackageTableController(TableController): + + def __init__(self): + self.table = DataPackage diff --git a/FreeTAKServer/controllers/DatabaseControllers/DatabaseController.py b/FreeTAKServer/controllers/DatabaseControllers/DatabaseController.py new file mode 100644 index 00000000..22f4141c --- /dev/null +++ b/FreeTAKServer/controllers/DatabaseControllers/DatabaseController.py @@ -0,0 +1,188 @@ +from FreeTAKServer.controllers.DatabaseControllers import UserTableController, DataPackageTableController +from FreeTAKServer.controllers.DatabaseControllers import VideoStreamTableController +from FreeTAKServer.controllers.DatabaseControllers import EventTableController +from sqlalchemy.orm import sessionmaker +from sqlalchemy import create_engine +from FreeTAKServer.model.SQLAlchemy.Root import Base +from FreeTAKServer.controllers.configuration.DatabaseConfiguration import DatabaseConfiguration +import FreeTAKServer.model.SQLAlchemy.CoTTables.Archive +import FreeTAKServer.model.SQLAlchemy.CoTTables._Group +import FreeTAKServer.model.SQLAlchemy.CoTTables.Chat +import FreeTAKServer.model.SQLAlchemy.CoTTables.Color +import FreeTAKServer.model.SQLAlchemy.CoTTables.Contact +import FreeTAKServer.model.SQLAlchemy.CoTTables.Dest +import FreeTAKServer.model.SQLAlchemy.CoTTables.Emergency +import FreeTAKServer.model.SQLAlchemy.CoTTables.Link +import FreeTAKServer.model.SQLAlchemy.CoTTables.Marti +import FreeTAKServer.model.SQLAlchemy.CoTTables.Precisionlocation +import FreeTAKServer.model.SQLAlchemy.CoTTables.Remarks +import FreeTAKServer.model.SQLAlchemy.CoTTables.Serverdestination +import FreeTAKServer.model.SQLAlchemy.CoTTables.Status +import FreeTAKServer.model.SQLAlchemy.CoTTables.Summary +import FreeTAKServer.model.SQLAlchemy.CoTTables.Takv +import FreeTAKServer.model.SQLAlchemy.CoTTables.Track +import FreeTAKServer.model.SQLAlchemy.CoTTables.Uid +import FreeTAKServer.model.SQLAlchemy.CoTTables.Usericon +import FreeTAKServer.model.SQLAlchemy.DataPackage +import FreeTAKServer.model.SQLAlchemy.VideoStream +import FreeTAKServer.model.SQLAlchemy.User + + +class DatabaseController: + """ + this controller should only be instantiated once for + each database connection to be established. this + function is the entry point for any classes attempting + to access the database + """ + + def __init__(self): + self.engine = self.create_engine() + self.SessionMaker = self.create_Sessionmaker() + self.session = self.create_Session() + self.DataPackageController = DataPackageTableController.DataPackageTableController() + self.UserTableController = UserTableController.UserTableController() + self.VideoStreamTableController = VideoStreamTableController.VideoStreamTableController() + self.EventTableController = EventTableController.EventTableController() + + def create_engine(self): + """ + this function creates the engine and applies all the metadata + of classes which inherit the base class and applies it to the database + to create tables. + TODO: move database path to constants + :arg + """ + engine = create_engine(DatabaseConfiguration().DataBaseConnectionString) + Base.metadata.create_all(engine) + return engine + + def create_Sessionmaker(self): + SessionMaker = sessionmaker(bind=self.engine) + return SessionMaker + + def create_Session(self): + """ + this function creates the session with the server + via the engine + :param engine: + :return: + """ + session = self.SessionMaker() + return session + + def create_datapackage(self, **args): + return self._create(self.DataPackageController, **args) + + def remove_datapackage(self, query="1 == 1"): + ''' + :param query: this parameter will be used to select which datapackages are deleted + :return: 1 on success + ''' + return self._remove(controller=self.DataPackageController, query=query) + + def query_datapackage(self, query="1 == 1", column=['*']): + return self._query(controller=self.DataPackageController, query=query, columns=column) + + def update_datapackage(self, column_value=None, query="1 == 1"): + return self._update(controller=self.DataPackageController, query=query, column_value=column_value) + + def _create(self, controller, **args): + controller.create(session=self.session, **args) + return 1 + + def _remove(self, controller, query): + controller.delete(session=self.session, query=query) + return 1 + + def _query(self, controller, query, columns): + return controller.query(session=self.session, query=query, columns = columns) + + def _update(self, controller, column_value, query): + return controller.update(session = self.session, column_value=column_value, query=query) + + def create_user(self, **args): + try: + return self._create(controller=self.UserTableController, **args) + except Exception as e: + self.session.rollback() + self.session.commit() + def remove_user(self, query="1 == 1"): + ''' + :param query: this parameter will be used to select which datapackages are deleted + :return: 1 on success + ''' + return self._remove(controller=self.UserTableController, query=query) + + def query_user(self, query="1 == 1", column=['*']): + return self._query(controller=self.UserTableController, query=query, columns=column) + + def update_user(self, column_value=dict(), query="1 == 1"): + return self._update(controller=self.UserTableController, query=query, column_value=column_value) + + def create_videostream(self, **args): + return self._create(controller=self.VideoStreamTableController, **args) + + def remove_videostream(self, query="1 == 1"): + ''' + :param query: this parameter will be used to select which datapackages are deleted + :return: 1 on success + ''' + return self._remove(controller=self.VideoStreamTableController, query=query) + + def query_videostream(self, query="1 == 1", column=['*']): + return self._query(controller=self.VideoStreamTableController, query=query, columns=column) + + def update_videostream(self, column_value=dict(), query="1 == 1"): + return self._update(controller=self.VideoStreamTableController, query=query, column_value=column_value) + + def create_CoT(self, object): + try: + session = self.create_Session() + output = self.EventTableController.create(session, object) + session.close() + return output + except Exception as e: + session.rollback() + session.close() + def remove_CoT(self, query="1 == 1"): + ''' + :param query: this parameter will be used to select which datapackages are deleted + :return: 1 on success + ''' + return self._remove(controller=self.EventTableController, query=query) + + def query_CoT(self, query="1 == 1", column=['*']): + return self._query(controller=self.EventTableController, query=query, columns=column) + + def update_CoT(self, column_value=dict(), query="1 == 1"): + return self._update(controller=self.EventTableController, query=query, column_value=column_value) + + def shutdown_Connection(self): + self.session.close() + self.engine.dispose() + +if __name__ == "__main__": + contr = DatabaseController() + import datetime as dt + contr.create_datapackage(uid='9', CreatorUid='abc123', Hash='36e4506f4d6a9582fc60529525c55f3ebd42b887b5164d24e44b85d7ea686a3d', Keywords="foobar", MIMEType="aaa/bbb", Name="other", Privacy=1, Size=32, SubmissionDateTime=dt.datetime.utcnow(), SubmissionUser="blue") + #contr.remove_datapackage('Hash == "36e4506f4d6a9582fc60529525c55f3ebd42b887b5164d24e44b85d7ea686a3d"') + #UID = 123 + #callsign = contr.query_user(query=f'uid == "{UID}"', column=['callsign']) + '''contr.(uid='9', CreatorUid='abc123', Hash='1bc21o', Keywords="foobar", MIMEType="aaa/bbb", Name="other", Privacy=1, Size=32, SubmissionDateTime=dt.datetime.utcnow(), SubmissionUser="blue") + from FreeTAKServer.controllers.SpecificCoTControllers.SendDropPointController import SendDropPointController + m = RawCoT() + m.dbController = contr + m.xmlString = "" + # m.xmlString = "" + x = SendDropPointController(m) + b = RawCoT() + b.dbController = contr + b.xmlString = 'DEFAULT' + x = SendDropPointController(b) + #y = x.getObject() + #contr.create_CoT(y.modelObject) + x = contr.session.query(Event).all()[-1] + #contr.create_user(callsign = 'abc') + #import operator + #a = contr.query_datapackage("uid == 423")''' diff --git a/FreeTAKServer/controllers/DatabaseControllers/EventTableController.py b/FreeTAKServer/controllers/DatabaseControllers/EventTableController.py new file mode 100644 index 00000000..ceb09d72 --- /dev/null +++ b/FreeTAKServer/controllers/DatabaseControllers/EventTableController.py @@ -0,0 +1,46 @@ +from FreeTAKServer.controllers.DatabaseControllers.TableController import TableController +from FreeTAKServer.model.SQLAlchemy.Event import Event +import importlib + +class EventTableController(TableController): + def __init__(self): + self.table = Event + + def create(self, session, object): + row = self.convert_model_to_row(modelObject=object) + session.add(row) + session.commit() + + def convert_model_to_row(self, modelObject, rowObject = None): + # TODO: find a more elegant way of doing this + if rowObject == None: + rowObject = Event() + else: + pass + for attribName, attribValue in modelObject.__dict__.items(): + if hasattr(attribValue, '__dict__'): + if attribName[0].isalpha(): + pass + else: + attribName[1].capitalize() + subRowObjectImport = importlib.import_module( + f'FreeTAKServer.model.SQLAlchemy.CoTTables.{attribName.capitalize()}') + subRowObject = getattr(subRowObjectImport, attribName.capitalize())() + subTableRowObject = self.convert_model_to_row(attribValue, subRowObject) + setattr(rowObject, attribName, subTableRowObject) + + elif isinstance(attribValue, list): + if attribName[0].isalpha(): + pass + else: + attribName[1].capitalize() + subRowObjectImport = importlib.import_module( + f'FreeTAKServer.model.SQLAlchemy.CoTTables.{attribName.capitalize()}') + for element in attribValue: + subRowObject = getattr(subRowObjectImport, attribName.capitalize())() + subTableRowObject = self.convert_model_to_row(element, subRowObject) + setattr(subTableRowObject, "owner", rowObject) + + else: + setattr(rowObject, attribName, attribValue) + return rowObject \ No newline at end of file diff --git a/FreeTAKServer/controllers/DatabaseControllers/RootController.py b/FreeTAKServer/controllers/DatabaseControllers/RootController.py new file mode 100644 index 00000000..face8f4a --- /dev/null +++ b/FreeTAKServer/controllers/DatabaseControllers/RootController.py @@ -0,0 +1,36 @@ +####################################################### +# +# RootController.py +# Python implementation of the Class TableController +# Generated by Enterprise Architect +# Created on: 24-Sep-2020 4:49:08 PM +# Original author: natha +# +####################################################### + + +class RootController: + def __init__(self): + self.table = None + + def delete(self, session, query): + # this function removes a row from the datapackages table based on the uid + session.query(self.table).filter(text(query)).delete() + session.commit() + + def create(self, session, **args): + # this function adds a new row to the datapackages table + session.add(self.table(**args)) + session.commit() + + def query(self, session, query, columns): + # query needs to be applicable to datapackage object tuple(['DataPackage.'+x for x in columns]) + output = session.query(*tuple([getattr(self.table, x) if x != '*' else DataPackage for x in columns])).filter(text(query)).all() + return output + + def update(self, session, query, column_value): + DataPackages = session.query(self.table).filter(text(query)).all() #self.query(session, query, [column for column, value in column_value.items()]) + for dp in DataPackages: + for column, value in column_value.items(): + setattr(dp, column, value) + session.commit() \ No newline at end of file diff --git a/FreeTAKServer/controllers/DatabaseControllers/TableController.py b/FreeTAKServer/controllers/DatabaseControllers/TableController.py new file mode 100644 index 00000000..c38827ea --- /dev/null +++ b/FreeTAKServer/controllers/DatabaseControllers/TableController.py @@ -0,0 +1,35 @@ +import shutil +from sqlalchemy.sql import text + +class TableController: + # default constructor def __init__(self): + def __init__(self): + self.table = None + + + def delete(self, session, query): + # this function removes a row from the datapackages table based on the uid + session.query(self.table).filter(text(query)).delete(synchronize_session='fetch') + session.commit() + + + def create(self, session, **args): + # this function adds a new row to the datapackages table + session.add(self.table(**args)) + session.commit() + + + def query(self, session, query, columns): + # query needs to be applicable to datapackage object tuple(['DataPackage.'+x for x in columns]) + output = session.query(*tuple([getattr(self.table, x) if x != '*' else self.table for x in columns])).filter( + text(query)).all() + return output + + + def update(self, session, query, column_value): + DataPackages = session.query(self.table).filter( + text(query)).all() # self.query(session, query, [column for column, value in column_value.items()]) + for dp in DataPackages: + for column, value in column_value.items(): + setattr(dp, column, value) + session.commit() \ No newline at end of file diff --git a/FreeTAKServer/controllers/DatabaseControllers/UserTableController.py b/FreeTAKServer/controllers/DatabaseControllers/UserTableController.py new file mode 100644 index 00000000..dacf1ed2 --- /dev/null +++ b/FreeTAKServer/controllers/DatabaseControllers/UserTableController.py @@ -0,0 +1,15 @@ +####################################################### +# +# UserTableController.py +# Python implementation of the Class UserTableController +# Generated by Enterprise Architect +# Created on: 24-Sep-2020 5:12:31 PM +# Original author: natha +# +####################################################### +from FreeTAKServer.controllers.DatabaseControllers.TableController import TableController +from FreeTAKServer.model.SQLAlchemy.User import User + +class UserTableController(TableController): + def __init__(self): + self.table = User \ No newline at end of file diff --git a/FreeTAKServer/controllers/DatabaseControllers/VideoStreamTableController.py b/FreeTAKServer/controllers/DatabaseControllers/VideoStreamTableController.py new file mode 100644 index 00000000..2117b459 --- /dev/null +++ b/FreeTAKServer/controllers/DatabaseControllers/VideoStreamTableController.py @@ -0,0 +1,16 @@ +####################################################### +# +# VideoStreamTableController.py +# Python implementation of the Class VideoStreamTableController +# Generated by Enterprise Architect +# Created on: 24-Sep-2020 8:19:58 PM +# Original author: natha +# +####################################################### +from FreeTAKServer.controllers.DatabaseControllers.TableController import TableController +from FreeTAKServer.model.SQLAlchemy.VideoStream import VideoStream + +class VideoStreamTableController(TableController): + + def __init__(self): + self.table = VideoStream \ No newline at end of file diff --git a/FreeTAKServer/controllers/DatabaseControllers/__init__.py b/FreeTAKServer/controllers/DatabaseControllers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/controllers/FilterGroupController.py b/FreeTAKServer/controllers/FilterGroupController.py new file mode 100644 index 00000000..3b657e8f --- /dev/null +++ b/FreeTAKServer/controllers/FilterGroupController.py @@ -0,0 +1,12 @@ +class FilterGroupController: + def __init__(self, filterGroups): + self.filterGroups = filterGroups + + def sendCoT(self, CoT): + pass + + def addUser(self, clientInformation): + pass + + def removeUser(self, clientInformation): + pass \ No newline at end of file diff --git a/FreeTAKServer/controllers/MainSocketController.py b/FreeTAKServer/controllers/MainSocketController.py index d23f3ffb..fa06d812 100644 --- a/FreeTAKServer/controllers/MainSocketController.py +++ b/FreeTAKServer/controllers/MainSocketController.py @@ -7,8 +7,8 @@ # Original author: Natha Paquette # ####################################################### -from FreeTAKServer.controllers.model.MainSocket import MainSocket -import socket +from FreeTAKServer.model.sockets.MainSocket import MainSocket + class MainSocketController: def __init__(self): @@ -21,7 +21,4 @@ def changePort(self, port): self.MainSocket.port = port def createSocket(self): - self.MainSocket.sock = socket.socket(self.MainSocket.socketAF, self.MainSocket.socketSTREAM) - self.MainSocket.sock.setsockopt(self.MainSocket.solSock, self.MainSocket.soReuseAddr, self.MainSocket.sockProto) - self.MainSocket.sock.bind((self.MainSocket.ip, self.MainSocket.port)) - return self.MainSocket.sock \ No newline at end of file + pass \ No newline at end of file diff --git a/FreeTAKServer/controllers/ProcessDataController.py b/FreeTAKServer/controllers/ProcessDataController.py new file mode 100644 index 00000000..bec04298 --- /dev/null +++ b/FreeTAKServer/controllers/ProcessDataController.py @@ -0,0 +1,3 @@ +import copy +class ProcessDataController: + pass diff --git a/FreeTAKServer/controllers/ReceiveConnections.py b/FreeTAKServer/controllers/ReceiveConnections.py index 00697827..c4888f9d 100644 --- a/FreeTAKServer/controllers/ReceiveConnections.py +++ b/FreeTAKServer/controllers/ReceiveConnections.py @@ -8,12 +8,8 @@ # ####################################################### import socket -import time -from logging.handlers import RotatingFileHandler -import logging from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants -import sys -from FreeTAKServer.controllers.model.RawConnectionInformation import RawConnectionInformation as sat +from FreeTAKServer.model.RawConnectionInformation import RawConnectionInformation as sat from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController from FreeTAKServer.controllers.configuration.ReceiveConnectionsConstants import ReceiveConnectionsConstants loggingConstants = LoggingConstants() diff --git a/FreeTAKServer/controllers/ReceiveConnectionsProcessController.py b/FreeTAKServer/controllers/ReceiveConnectionsProcessController.py index b296fd60..ef48f338 100644 --- a/FreeTAKServer/controllers/ReceiveConnectionsProcessController.py +++ b/FreeTAKServer/controllers/ReceiveConnectionsProcessController.py @@ -7,7 +7,7 @@ # Original author: Natha Paquette # ####################################################### -from FreeTAKServer.controllers.model.ReceiveConnectionsProcess import ReceiveConnectionsProcess +from FreeTAKServer.model.ReceiveConnectionsProcess import ReceiveConnectionsProcess class ReceiveConnectionsProcessController: def __init__(self): diff --git a/FreeTAKServer/controllers/SendClientData.py b/FreeTAKServer/controllers/SendClientData.py index c390e52c..572fb3e1 100644 --- a/FreeTAKServer/controllers/SendClientData.py +++ b/FreeTAKServer/controllers/SendClientData.py @@ -8,10 +8,7 @@ # ####################################################### -from logging.handlers import RotatingFileHandler -import logging from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants -import sys from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController logger = CreateLoggerController("SendClientData").getLogger() diff --git a/FreeTAKServer/controllers/SendDataController.py b/FreeTAKServer/controllers/SendDataController.py index b423e2f4..f63aac32 100644 --- a/FreeTAKServer/controllers/SendDataController.py +++ b/FreeTAKServer/controllers/SendDataController.py @@ -1,78 +1,134 @@ -from logging.handlers import RotatingFileHandler -import logging from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants -import sys from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController loggingConstants = LoggingConstants() logger = CreateLoggerController("SendDataController").getLogger() - +import copy +#TODO: the part handling new connection from seperate process needs to be cleaned up class SendDataController: def __init__(self): pass - def sendDataInQueue(self, sender, processedCoT, clientInformationQueue): + def sendDataInQueue(self, sender, processedCoT, clientInformationQueue, shareDataPipe = None): try: - try: - if processedCoT.type == 'GeoChat': - return self.geochat_sending(clientInformationQueue, processedCoT, sender) - else: - pass - except: - pass - - if sender == processedCoT: + print('sending data to fts client' + str(processedCoT.xmlString)) + except Exception as e: + print(e) + try: + if processedCoT.type == 'GeoChat': + self.returnData = self.geochat_sending(clientInformationQueue, processedCoT, sender, shareDataPipe) + return self.returnData + elif sender == processedCoT: for client in clientInformationQueue: try: sock = client.socket sock.send(processedCoT.idData.encode()) sender.socket.send(client.idData.encode()) - except: + # this is a special case which is identified + # by the server due to the list contents + # being within a list + except Exception as e: logger.error('error in sending connection data ' + str(processedCoT.idData)) - return -1 + pass + copiedProcessedCoTObject = copy.deepcopy(processedCoT) + copiedProcessedCoTObject.idData = copiedProcessedCoTObject.idData.encode() + shareDataPipe.send([copiedProcessedCoTObject]) return 1 - - + elif processedCoT.type == 'other': + self.returnData = self.send_to_specific_client(clientInformationQueue, processedCoT, sender, shareDataPipe) + return self.returnData else: - return self.send_to_all(clientInformationQueue, processedCoT, sender) + self.returnData = self.send_to_all(clientInformationQueue, processedCoT, sender, shareDataPipe) + return self.returnData except Exception as e: logger.error(loggingConstants.SENDDATACONTROLLERSENDDATAINQUEUEERROR+str(e)) return -1 - def send_to_all(self, clientInformationQueue, processedCoT, sender): - for client in clientInformationQueue: - if client != sender: + def send_to_specific_client(self, clientInformationQueue, processedCoT, sender, shareDataPipe): + try: + if processedCoT.martiPresent == False: + print('marti not present') + return self.send_to_all(clientInformationQueue, processedCoT, sender, shareDataPipe) + else: + print('marti present') + for dest in processedCoT.modelObject.detail.marti.dest: + try: + for client in clientInformationQueue: + if client.modelObject.detail.contact.callsign == dest.callsign: + print('client socket is ' + str(client.socket)) + sock = client.socket + try: + sock.send(processedCoT.xmlString) + except Exception as e: + logger.error('error sending data with marti to client data ' + str( + processedCoT.xmlString) + 'error is ' + str(e)) + return (-1, client) + else: + continue + except Exception as e: + logger.error('error sending data with marti to client within if data is ' + str( + processedCoT.xmlString) + 'error is ' + str(e)) + return -1 + if shareDataPipe != None: + processedCoT.clientInformation = None + shareDataPipe.send(processedCoT) + else: + pass + return 1 + except Exception as e: + logger.error('error in send data to specific client ' + str(e)) + return -1 + def send_to_all(self, clientInformationQueue, processedCoT, sender, shareDataPipe): + try: + for client in clientInformationQueue: + sock = client.socket try: - print(processedCoT.xmlString) - sock.send(processedCoT.xmlString) + if hasattr(processedCoT, 'xmlString'): + print('sending to all ' + str(processedCoT.xmlString)) + sock.send(processedCoT.xmlString) + else: + sock.send(processedCoT.idData.encode()) except Exception as e: + print(e) logger.error('error in sending of data ' + str(processedCoT.xmlString)) return (-1, client) + if shareDataPipe != None: + processedCoT.clientInformation = None + shareDataPipe.send(processedCoT) else: - continue - return 1 - - def geochat_sending(self, clientInformationQueue, processedCoT, sender): - if processedCoT.modelObject.detail._chat.chatgrp.uid1 == 'All Chat Rooms': - return self.send_to_all(clientInformationQueue, processedCoT, sender) - - else: - for client in clientInformationQueue: - try: - if client.modelObject.uid == processedCoT.modelObject.detail._chat.chatgrp.uid1: - sock = client.socket - try: - sock.send(processedCoT.xmlString) - except Exception as e: - logger.error('error sending data with marti to client data ' + str( - processedCoT.xmlString) + 'error is ' + str(e)) - return (-1, client) - else: - continue - except Exception as e: - logger.error('error sending data with marti to client within if data is ' + str( - processedCoT.xmlString) + 'error is ' + str(e)) - return -1 - return 1 \ No newline at end of file + pass + return 1 + except Exception as e: + logger.error('error in send to all ' + str(e)) + def geochat_sending(self, clientInformationQueue, processedCoT, sender, shareDataPipe): + try: + if processedCoT.modelObject.detail._chat.chatgrp.uid1 == 'All Chat Rooms': + return self.send_to_all(clientInformationQueue, processedCoT, sender, shareDataPipe) + + else: + for client in clientInformationQueue: + try: + if client.modelObject.uid == processedCoT.modelObject.detail._chat.chatgrp.uid1: + sock = client.socket + try: + sock.send(processedCoT.xmlString) + except Exception as e: + logger.error('error sending data with marti to client data ' + str( + processedCoT.xmlString) + 'error is ' + str(e)) + return (-1, client) + else: + continue + except Exception as e: + logger.error('error sending data with marti to client within if data is ' + str( + processedCoT.xmlString) + 'error is ' + str(e)) + return -1 + if shareDataPipe != None: + processedCoT.clientInformation = None + shareDataPipe.send(processedCoT) + else: + pass + return 1 + except Exception as e: + logger.error('there has been an exception in sending geochat ' + str(e)) \ No newline at end of file diff --git a/FreeTAKServer/controllers/SpecificCoTControllers/SendCoTAbstractController.py b/FreeTAKServer/controllers/SpecificCoTControllers/SendCoTAbstractController.py new file mode 100644 index 00000000..59c69ffa --- /dev/null +++ b/FreeTAKServer/controllers/SpecificCoTControllers/SendCoTAbstractController.py @@ -0,0 +1,68 @@ +from lxml import etree +from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants +from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController +from FreeTAKServer.model.FTSModel.Event import Event as event +from FreeTAKServer.controllers.configuration.MainConfig import MainConfig + +loggingConstants = LoggingConstants() +logger = CreateLoggerController("SendCoTAbstract").getLogger() + +class SendCoTAbstractController: + Event = event + def __init__(self, object): + pass + + def fill_object(self, object, tempObject, RawCoT, addToDB = MainConfig.SaveCoTToDB): + try: + object.modelObject = self.create_model_object(tempObject, RawCoT.xmlString) + except Exception as e: + logger.error('there has been an exception in the creation of a model object ' + str(e)) + try: + object.xmlString = self.create_xml_string(object.modelObject) + except Exception as e: + logger.error('there has been an exception in the creation of a xmlString ' + str(e)) + try: + if addToDB == True: + RawCoT.dbController.create_CoT(object.modelObject) + else: + pass + except Exception as e: + logger.error('there has been an exception in the creation of a database instance of this object ' + str(e)) + + self.setObject(object) + + def create_model_object(self, tempObject, xmlString): + """ + this function takes an empty model object and xml as arguments and then calls the serializer within the xmlcotcontroller + module which returns a model object occupied with all the data from the CoT + """ + from FreeTAKServer.controllers.XMLCoTController import XMLCoTController + + try: + modelInstance = XMLCoTController().serialize_CoT_to_model(tempObject, + etree.fromstring(xmlString)) + return modelInstance + except Exception as e: + logger.error('there has been an exception in the creation of the model object ' + str(e)) + return -1 + def create_xml_string(self, modelObject): + """ + this function calls the model to xml serializer within XMLCoTController + with an instantiated model object supplied in the function argument + """ + from FreeTAKServer.controllers.XMLCoTController import XMLCoTController + try: + xml = XMLCoTController().serialize_model_to_CoT(modelObject, 'event') + return xml + except Exception as e: + logger.error('there has been an exception in the creation of the xml string ' +str(e)) + return -1 + + def setObject(self, object): + self.Object = object + + def getObject(self): + return self.Object + + def reloadXmlString(self): + self.Object.xmlString = self.create_xml_string(self.Object.modelObject) \ No newline at end of file diff --git a/FreeTAKServer/controllers/SpecificCoTControllers/SendDisconnectController.py b/FreeTAKServer/controllers/SpecificCoTControllers/SendDisconnectController.py new file mode 100644 index 00000000..26b286f5 --- /dev/null +++ b/FreeTAKServer/controllers/SpecificCoTControllers/SendDisconnectController.py @@ -0,0 +1,17 @@ +from FreeTAKServer.model.SpecificCoT.SendDisconnect import SendDisconnect +from .SendCoTAbstractController import SendCoTAbstractController +from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants +from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController + +loggingConstants = LoggingConstants() +logger = CreateLoggerController("SendDisconnectController").getLogger() + +class SendDisconnectController(SendCoTAbstractController): + def __init__(self, RawCoT): + try: + tempObject = super().Event.disconnect() + object = SendDisconnect() + self.fill_object(object, tempObject, RawCoT, addToDB=False) + except Exception as e: + logger.error("there has been an exception in the creation of the send disconnect object " + str(e)) + return -1 \ No newline at end of file diff --git a/FreeTAKServer/controllers/SpecificCoTControllers/SendDropPointController.py b/FreeTAKServer/controllers/SpecificCoTControllers/SendDropPointController.py new file mode 100644 index 00000000..dc7d4e66 --- /dev/null +++ b/FreeTAKServer/controllers/SpecificCoTControllers/SendDropPointController.py @@ -0,0 +1,17 @@ +from FreeTAKServer.model.SpecificCoT.SendDropPoint import SendDropPoint +from .SendCoTAbstractController import SendCoTAbstractController +from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants +from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController + +loggingConstants = LoggingConstants() +logger = CreateLoggerController("SendDropPointController").getLogger() + +class SendDropPointController(SendCoTAbstractController): + def __init__(self, RawCoT): + try: + tempObject = super().Event.dropPoint() + object = SendDropPoint() + self.fill_object(object, tempObject, RawCoT) + except Exception as e: + logger.error("there has been an exception in the creation of the send drop point object " + str(e)) + return -1 \ No newline at end of file diff --git a/FreeTAKServer/controllers/SpecificCoTControllers/SendEmergencyController.py b/FreeTAKServer/controllers/SpecificCoTControllers/SendEmergencyController.py new file mode 100644 index 00000000..9ad00970 --- /dev/null +++ b/FreeTAKServer/controllers/SpecificCoTControllers/SendEmergencyController.py @@ -0,0 +1,19 @@ +from FreeTAKServer.controllers.SpecificCoTControllers.SendCoTAbstractController import SendCoTAbstractController +from FreeTAKServer.model.FTSModel.Event import Event +from FreeTAKServer.model.SpecificCoT.SendEmergency import SendEmergency +from FreeTAKServer.controllers.XMLCoTController import XMLCoTController + +class SendEmergencyController(SendCoTAbstractController): + def __init__(self, RawCoT): + if RawCoT.status == 'on': + tempObject = super().Event.emergecyOn() + object = SendEmergency() + object.status = 'on' + self.fill_object(object, tempObject, RawCoT) + + + elif RawCoT.status == 'off': + tempObject = super().Event.emergecyOff() + object = SendEmergency() + object.status = 'off' + self.fill_object(object, tempObject, RawCoT) \ No newline at end of file diff --git a/FreeTAKServer/controllers/SpecificCoTControllers/SendGeoChatController.py b/FreeTAKServer/controllers/SpecificCoTControllers/SendGeoChatController.py new file mode 100644 index 00000000..702c0342 --- /dev/null +++ b/FreeTAKServer/controllers/SpecificCoTControllers/SendGeoChatController.py @@ -0,0 +1,18 @@ +from FreeTAKServer.model.SpecificCoT.SendGeoChat import SendGeoChat +from .SendCoTAbstractController import SendCoTAbstractController +from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants +from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController + +loggingConstants = LoggingConstants() +logger = CreateLoggerController("SendGeoChatController").getLogger() + +class SendGeoChatController(SendCoTAbstractController): + def __init__(self, RawCoT): + try: + tempObject = super().Event.GeoChat() + object = SendGeoChat() + self.fill_object(object, tempObject, RawCoT) + except Exception as e: + logger.error("there has been an exception in the creation" + " of the send Geo Chat object " + str(e)) + return -1 \ No newline at end of file diff --git a/FreeTAKServer/controllers/SpecificCoTControllers/SendHealthCheckController.py b/FreeTAKServer/controllers/SpecificCoTControllers/SendHealthCheckController.py new file mode 100644 index 00000000..42303777 --- /dev/null +++ b/FreeTAKServer/controllers/SpecificCoTControllers/SendHealthCheckController.py @@ -0,0 +1,12 @@ +from FreeTAKServer.model.SpecificCoT.SendHealthCheck import SendHealthCheck + +class SendHealthCheckController: + # TODO: deprecate this function + def __init__(self, RawCoT): + self.RawCoT = RawCoT + self.HealthCheck = SendHealthCheck() + self.HealthCheck.xmlString = RawCoT.xmlString + self.HealthCheck.clientInformation = RawCoT.clientInformation + + def getObject(self): + return self.HealthCheck \ No newline at end of file diff --git a/FreeTAKServer/controllers/SpecificCoTControllers/SendInvalidCoTController.py b/FreeTAKServer/controllers/SpecificCoTControllers/SendInvalidCoTController.py new file mode 100644 index 00000000..0b904660 --- /dev/null +++ b/FreeTAKServer/controllers/SpecificCoTControllers/SendInvalidCoTController.py @@ -0,0 +1,19 @@ +from FreeTAKServer.model.SpecificCoT.SendInvalidCoT import SendInvalidCoT +from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants +from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController + +loggingConstants = LoggingConstants() +logger = CreateLoggerController("SendInvalidCoTController").getLogger() + + +class SendInvalidCoTController: + def __init__(self, RawCOT): + try: + self.SendInvalidCoT = SendInvalidCoT() + self.SendInvalidCoT.clientInformation = RawCOT.clientInformation + except Exception as e: + logger.error("there has been an exception in the creation" + " of the send Invalid CoT object " + str(e)) + return -1 + def getObject(self): + return self.SendInvalidCoT \ No newline at end of file diff --git a/FreeTAKServer/controllers/SpecificCoTControllers/SendOtherController.py b/FreeTAKServer/controllers/SpecificCoTControllers/SendOtherController.py new file mode 100644 index 00000000..2ac8ce0d --- /dev/null +++ b/FreeTAKServer/controllers/SpecificCoTControllers/SendOtherController.py @@ -0,0 +1,49 @@ +from lxml import etree +from FreeTAKServer.model.SpecificCoT.SendOther import SendOther +from .SendCoTAbstractController import SendCoTAbstractController +from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants +from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController + +loggingConstants = LoggingConstants() +logger = CreateLoggerController("SendOtherController").getLogger() +class SendOtherController(SendCoTAbstractController): + def __init__(self, RawCoT): + if type(RawCoT != bytes): + pass + else: + RawCoT.xmlString.encode() + try: + tempObject = super().Event.Other() + self.object = SendOther() + xml = RawCoT.xmlString + RawCoT.xmlString = etree.tostring(self.filter_CoT(xml)) + self.fill_object(self.object, tempObject, RawCoT) + try: + object = self.getObject() + + except Exception as e: + logger.error("there has been an exception getting object " + str(e)) + self.Object.setXmlString(xml) + except Exception as e: + logger.error("there has been an exception in the creation of an" + "Other object " + str(e)) + #this function modifies the CoT so only the marti and point tags are present + def filter_CoT(self, event): + try: + outputEvent = etree.fromstring(event) + tempDetail = outputEvent.find('detail') + outputEvent.remove(tempDetail) + detail = etree.fromstring(event).find('detail') + try: + marti = detail.find('marti') + outputDetail = etree.SubElement(outputEvent, 'detail') + outputDetail.append(marti) + print('dest client found') + self.object.martiPresent = True + except: + etree.SubElement(outputEvent, 'detail') + print('no dest client found') + + return outputEvent + except Exception as e: + print('exception filtering CoT ' + str(e)) \ No newline at end of file diff --git a/FreeTAKServer/controllers/SpecificCoTControllers/SendPingController.py b/FreeTAKServer/controllers/SpecificCoTControllers/SendPingController.py new file mode 100644 index 00000000..39c18c21 --- /dev/null +++ b/FreeTAKServer/controllers/SpecificCoTControllers/SendPingController.py @@ -0,0 +1,18 @@ +from FreeTAKServer.model.SpecificCoT.SendTakPong import SendTakPong +from .SendCoTAbstractController import SendCoTAbstractController + +from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants +from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController + +loggingConstants = LoggingConstants() +logger = CreateLoggerController("SendInvalidCoTController").getLogger() +class SendPingController(SendCoTAbstractController): + def __init__(self, RawCoT): + try: + RawCoT.xmlString = b'' + tempObject = super().Event.takPong() + object = SendTakPong() + self.fill_object(object, tempObject, RawCoT, addToDB = False) + except Exception as e: + logger.error("there has been an exception in" + " the creation of a Ping model object " + str(e)) \ No newline at end of file diff --git a/FreeTAKServer/controllers/SpecificCoTControllers/SendTakPongController.py b/FreeTAKServer/controllers/SpecificCoTControllers/SendTakPongController.py new file mode 100644 index 00000000..690aea26 --- /dev/null +++ b/FreeTAKServer/controllers/SpecificCoTControllers/SendTakPongController.py @@ -0,0 +1,9 @@ +from .SendCoTAbstractController import SendCoTAbstractController +from FreeTAKServer.model.SpecificCoT.SendTakPong import SendTakPong + + +class SendTakPongController(SendCoTAbstractController): + def __init__(self, RawCoT): + tempObject = super().Event.takPong() + object = SendTakPong() + self.fill_object(object, tempObject, RawCoT) \ No newline at end of file diff --git a/FreeTAKServer/controllers/SpecificCoTControllers/SendUserUpdateController.py b/FreeTAKServer/controllers/SpecificCoTControllers/SendUserUpdateController.py new file mode 100644 index 00000000..a57d58d7 --- /dev/null +++ b/FreeTAKServer/controllers/SpecificCoTControllers/SendUserUpdateController.py @@ -0,0 +1,11 @@ +from .SendCoTAbstractController import SendCoTAbstractController +from FreeTAKServer.model.SpecificCoT.SendUserUpdate import SendUserUpdate + +class SendUserUpdateController(SendCoTAbstractController): + def __init__(self, RawCoT): + try: + tempObject = super().Event.UserUpdate() + object = SendUserUpdate() + self.fill_object(object, tempObject, RawCoT) + except Exception as e: + print('send user update exception ' + str(e)) diff --git a/FreeTAKServer/controllers/SpecificCoTControllers/__init__.py b/FreeTAKServer/controllers/SpecificCoTControllers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/controllers/TCPSocketController.py b/FreeTAKServer/controllers/TCPSocketController.py new file mode 100644 index 00000000..9c4851c8 --- /dev/null +++ b/FreeTAKServer/controllers/TCPSocketController.py @@ -0,0 +1,9 @@ +from FreeTAKServer.controllers.MainSocketController import MainSocketController +import socket + +class TCPSocketController(MainSocketController): + def createSocket(self): + self.MainSocket.sock = socket.socket(self.MainSocket.socketAF, self.MainSocket.socketSTREAM) + self.MainSocket.sock.setsockopt(self.MainSocket.solSock, self.MainSocket.soReuseAddr, self.MainSocket.sockProto) + self.MainSocket.sock.bind((self.MainSocket.ip, self.MainSocket.port)) + return self.MainSocket.sock \ No newline at end of file diff --git a/FreeTAKServer/controllers/XMLCoTController.py b/FreeTAKServer/controllers/XMLCoTController.py index d0897ce5..c035a7f2 100644 --- a/FreeTAKServer/controllers/XMLCoTController.py +++ b/FreeTAKServer/controllers/XMLCoTController.py @@ -7,17 +7,10 @@ # Original author: Natha Paquette # ####################################################### -#TODO: add more rigid exception management from lxml import etree -from logging.handlers import RotatingFileHandler -import logging from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants -import sys -from FreeTAKServer.controllers.configuration.OrchestratorConstants import OrchestratorConstants from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController -from FreeTAKServer.controllers.model.Event import Event -import inspect -import types + logger = CreateLoggerController("XMLCoTController").getLogger() loggingConstants = LoggingConstants() @@ -46,6 +39,15 @@ def determineCoTGeneral(self, data): except Exception as e: logger.error(loggingConstants.XMLCOTCONTROLLERDETERMINECOTGENERALERRORB+str(e)) + def convert_model_to_row(self, modelObject, rowObject): + for attribName, attribValue in modelObject.__dict__.items(): + if hasattr(attribValue, '__dict__'): + subTableRow = getattr(rowObject, attribName) + subTableRowObject = self.convert_model_to_row(attribValue, subTableRow) + setattr(rowObject, attribName, subTableRowObject) + else: + setattr(rowObject, attribName, attribValue) + def determineCoTType(self, RawCoT): # this function is to establish which specific controller applys to the CoT if any try: @@ -63,7 +65,8 @@ def determineCoTType(self, RawCoT): "health": "SendHealthCheckController", "ping": "SendPingController", "geochat": "SendGeoChatController", - "point": "SendDropPointController" + "point": "SendDropPointController", + "userupdate": "SendUserUpdateController" } # TODO: the below if statement is probably unnecessary but this needs to be verified if RawCoT == b'' or RawCoT == None: @@ -78,10 +81,6 @@ def determineCoTType(self, RawCoT): except: RawCoT.status = 'on' - elif detail.find('healthCheck') != None: - RawCoT.CoTType = CoTTypes['health'] - return RawCoT - elif str(event.attrib['type']) == "t-x-c-t": RawCoT.CoTType = CoTTypes['ping'] return RawCoT @@ -90,6 +89,10 @@ def determineCoTType(self, RawCoT): RawCoT.CoTType = CoTTypes['geochat'] return RawCoT + elif str(event.attrib['type']) == "a-f-G-U-C": + RawCoT.CoTType = CoTTypes['userupdate'] + return RawCoT + elif str(event.attrib['type']) == "a-h-G" or str(event.attrib['type']) == "a-n-G" or str(event.attrib['type']) == "a-f-G" or str(event.attrib['type']) == "a-u-G": RawCoT.CoTType = CoTTypes['point'] return RawCoT @@ -111,15 +114,18 @@ def findMarti(self): def findUID(self): pass - def serialize_model_to_CoT(self, modelObject, tagName, level = 0): + def serialize_model_to_CoT(self, modelObject, tagName = 'event', level = 0): xml = etree.Element(tagName) for attribName, value in modelObject.__dict__.items(): if hasattr(value, '__dict__'): tagElement = self.serialize_model_to_CoT(value, attribName, level = level + 1) - # handles instances in which tag name begins with double underscore - if attribName[0] == '_': - tagElement.tag = '_' + tagElement.tag - xml.append(tagElement) + # TODO: modify so double underscores are handled differently + try: + if attribName[0] == '_': + tagElement.tag = '_' + tagElement.tag + xml.append(tagElement) + except: + pass else: xml.append(tagElement) @@ -129,10 +135,13 @@ def serialize_model_to_CoT(self, modelObject, tagName, level = 0): elif isinstance(value, list): for element in value: tagElement = self.serialize_model_to_CoT(element, attribName, level=level + 1) - # handles instances in which tag name begins with double underscore - if attribName[0] == '_': - tagElement.tag = '_' + tagElement.tag - xml.append(tagElement) + # TODO: modify so double underscores are handled differently + try: + if attribName[0] == '_': + tagElement.tag = '_' + tagElement.tag + xml.append(tagElement) + except: + pass else: xml.append(tagElement) @@ -141,11 +150,15 @@ def serialize_model_to_CoT(self, modelObject, tagName, level = 0): xml.text = value else: + # TODO: modify so double underscores are handled differently # handles instances in which attribute name begins with double underscore - if attribName[0] == '_': - xml.attrib['_'+attribName] = value + try: + if attribName[0] == '_': + xml.attrib['_'+attribName] = value + except: + pass else: - xml.attrib[attribName] = value + xml.attrib[attribName] = str(value) if level == 0: return etree.tostring(xml) diff --git a/FreeTAKServer/controllers/configuration/DataPackageServerConstants.py b/FreeTAKServer/controllers/configuration/DataPackageServerConstants.py index 854c98a9..330d5965 100644 --- a/FreeTAKServer/controllers/configuration/DataPackageServerConstants.py +++ b/FreeTAKServer/controllers/configuration/DataPackageServerConstants.py @@ -1,6 +1,6 @@ import os import pathlib - +from FreeTAKServer.controllers.configuration.MainConfig import MainConfig class DataPackageServerConstants: def __init__(self): @@ -15,7 +15,7 @@ def __init__(self): self.HTTPDEBUG = False self.HTTPMETHODS = ['POST', 'GET', 'PUT'] self.IP = "0.0.0.0" - self.versionInfo = 'FreeTAKServer-1.0RC3' + self.versionInfo = MainConfig.version self.NodeID = 'FTS' self.VERSIONJSON = '{"version":"2","type":"ServerConfig", "data":{"version": "%s", "api": "2","hostname":"%s"}, "nodeId":"%s"}' % ( self.versionInfo, "0.0.0.0", self.NodeID) diff --git a/FreeTAKServer/controllers/configuration/DatabaseConfiguration.py b/FreeTAKServer/controllers/configuration/DatabaseConfiguration.py new file mode 100644 index 00000000..c6b9bce4 --- /dev/null +++ b/FreeTAKServer/controllers/configuration/DatabaseConfiguration.py @@ -0,0 +1,7 @@ +from FreeTAKServer.controllers.configuration.MainConfig import MainConfig + +class DatabaseConfiguration: + DataBasePath = MainConfig.DBFilePath + DataBaseType = str('sqlite:///') + DataBaseConnectionString = str(DataBaseType+DataBasePath) + #DataBaseConnectionString = str('sqlite:////home/ghost/FTSTesting/FreeTAKServer/controllers/testing.db') diff --git a/FreeTAKServer/controllers/configuration/FTSDataBase.db b/FreeTAKServer/controllers/configuration/FTSDataBase.db new file mode 100644 index 00000000..7fc4a049 Binary files /dev/null and b/FreeTAKServer/controllers/configuration/FTSDataBase.db differ diff --git a/FreeTAKServer/controllers/configuration/MainConfig.py b/FreeTAKServer/controllers/configuration/MainConfig.py new file mode 100644 index 00000000..f8995732 --- /dev/null +++ b/FreeTAKServer/controllers/configuration/MainConfig.py @@ -0,0 +1,25 @@ +import os +currentPath = os.path.dirname(os.path.abspath(__file__)) + +class MainConfig: + """ + this is the main configuration file and is the only one which + should need to be changed + """ + # this is the port to which clients will connect + CoTServicePort = int(8087) + + # this needs to be changed for private data packages to work + DataPackageServiceDefaultIP = str("0.0.0.0") + + # whether or not to save CoT's to the DB + SaveCoTToDB = bool(False) + + # this should be set before startup + DBFilePath = str(currentPath + r'\FTSDataBase.db') + + # the version information of the server (recommended to leave as default) + version = 'FreeTAKServer-1.1' + + # set to None if you don't want a message sent + ConnectionMessage = f'Welcome to FreeTAKServer {version}. The Parrot is not dead. It’s just resting' \ No newline at end of file diff --git a/FreeTAKServer/controllers/configuration/OrchestratorConstants.py b/FreeTAKServer/controllers/configuration/OrchestratorConstants.py index 2852b18f..b3c7a425 100644 --- a/FreeTAKServer/controllers/configuration/OrchestratorConstants.py +++ b/FreeTAKServer/controllers/configuration/OrchestratorConstants.py @@ -1,13 +1,19 @@ + +from FreeTAKServer.controllers.configuration.MainConfig import MainConfig + class OrchestratorConstants: def __init__(self): self.CoTIP = "0.0.0.0" - self.COTPORT = 8087 + self.COTPORT = MainConfig.CoTServicePort self.APIPORTARG = '-APIPort' self.COTPORTARG = '-CoTPort' self.IPARG = "-IP" self.APIPORTDESC = 'the port address you would like FreeTAKServer to run receive datapackages on not' self.IPDESC = "the IP you would like FreeTAKServer to run receive connections on, must be set for private DataPackages to function" self.COTPORTDESC = 'the port you would like FreeTAKServer to run receive connections on' + self.COTIPDESC = 'the IP you would like FreeTAKServer to run receive connections on' self.FULLDESC = 'FreeTAKServer startup settings' self.HEALTHCHECK = 'HealthCheck' - self.LOCALHOST = '127.0.0.1' \ No newline at end of file + self.LOCALHOST = '127.0.0.1' + + self.DEFAULTCONNECTIONGEOCHATOBJ = MainConfig.ConnectionMessage \ No newline at end of file diff --git a/FreeTAKServer/controllers/configuration/RestAPIVariables.py b/FreeTAKServer/controllers/configuration/RestAPIVariables.py index 85f90ded..f1ef536e 100644 --- a/FreeTAKServer/controllers/configuration/RestAPIVariables.py +++ b/FreeTAKServer/controllers/configuration/RestAPIVariables.py @@ -23,14 +23,17 @@ def default_values(self): self.defaultPort = 80 self.defaultCoTIP = '0.0.0.0' self.defaultCoTPort = 15777 + self.defaultCoTStatus = '' self.defaultDataPackageIP = '0.0.0.0' self.defaultDataPackagePort = 8080 + self.defaultDataPackageStatus = '' def json_content(self): self.JsonStatusStartAll = {"CoTService": - {"IP": self.getdefaultCoTIP(), "PORT": self.getdefaultCoTPort(), "STATUS": "start"}, + {"IP": self.getdefaultCoTIP(), "PORT": self.getdefaultCoTPort(), "STATUS": self.getdefaultCoTStatus()}, "DataPackageService": - {"IP": self.getdefaultDataPackageIP(), "PORT": self.getdefaultDataPackagePort(), "STATUS": "start"}} + {"IP": self.getdefaultDataPackageIP(), "PORT": self.getdefaultDataPackagePort(), "STATUS": self.getdefaultDataPackageStatus()}} + self.JsonStatusStopAll = {"CoTService": {"STATUS": "stop"}, "DataPackageService": @@ -46,7 +49,7 @@ def getJsonStatusStartAll(self): def setdefaultCoTIP(self, defaultCoTIP): self.defaultCoTIP = defaultCoTIP - + def getdefaultCoTIP(self): return self.defaultCoTIP @@ -56,6 +59,12 @@ def setdefaultCoTPort(self, defaultCoTPort): def getdefaultCoTPort(self): return self.defaultCoTPort + def setdefaultCoTStatus(self, defaultCoTStatus): + self.defaultCoTStatus = defaultCoTStatus + + def getdefaultCoTStatus(self): + return self.defaultCoTStatus + def setdefaultDataPackageIP(self, defaultDataPackageIP): self.defaultDataPackageIP = defaultDataPackageIP @@ -66,4 +75,10 @@ def setdefaultDataPackagePort(self, defaultDataPackagePort): self.defaultDataPackagePort = defaultDataPackagePort def getdefaultDataPackagePort(self): - return self.defaultDataPackagePort \ No newline at end of file + return self.defaultDataPackagePort + + def setdefaultDataPackageStatus(self, defaultDataPackageStatus): + self.defaultDataPackageStatus = defaultDataPackageStatus + + def getdefaultDataPackageStatus(self): + return self.defaultDataPackageStatus \ No newline at end of file diff --git a/FreeTAKServer/controllers/logs/__init__.py b/FreeTAKServer/controllers/logs/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/controllers/services/DataPackageServer.py b/FreeTAKServer/controllers/services/DataPackageServer.py new file mode 100644 index 00000000..ea13e204 --- /dev/null +++ b/FreeTAKServer/controllers/services/DataPackageServer.py @@ -0,0 +1,261 @@ +import logging +import os +import random +import string +import traceback +import xml.etree.ElementTree as ET +from logging.handlers import RotatingFileHandler +from pathlib import Path, PurePath +from FreeTAKServer.controllers.configuration.DataPackageServerConstants import DataPackageServerConstants +from FreeTAKServer.controllers.configuration.SQLcommands import SQLcommands +from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants +from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController +from FreeTAKServer.controllers.DatabaseControllers.DatabaseController import DatabaseController +from FreeTAKServer.controllers.configuration.DatabaseConfiguration import DatabaseConfiguration + +loggingConstants = LoggingConstants() +logger = CreateLoggerController("DataPackageServer").getLogger() +from flask_sqlalchemy import SQLAlchemy +from flask import Flask, request, send_file +from flask.logging import default_handler + +dbController = DatabaseController() + +log = logging.getLogger('werkzeug') +log.setLevel(logging.ERROR) + +sql = SQLcommands() +const = DataPackageServerConstants() +log = LoggingConstants() + +app = Flask(__name__) # create the Flask app +app.config['SQLALCHEMY_DATABASE_URI'] = DatabaseConfiguration().DataBaseConnectionString +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False +db = SQLAlchemy(app) +# TODO: verify session life cycle in dbController doesnt break this logic +dbController.session = db.session +file_dir = os.path.dirname(os.path.realpath(__file__)) +dp_directory = PurePath(file_dir, const.DATAPACKAGEFOLDER) + +# Set up logging +if not Path(log.LOGDIRECTORY).exists(): + print(f"Creating directory at {log.LOGDIRECTORY}") + os.makedirs(log.LOGDIRECTORY) +app.logger.removeHandler(default_handler) +formatter = logging.Formatter(log.LOGFORMAT) +file_handler = RotatingFileHandler( + log.HTTPLOG, + maxBytes=log.MAXFILESIZE, + backupCount=log.BACKUPCOUNT +) +file_handler.setFormatter(formatter) +file_handler.setLevel(logging.ERROR) +#app.logger.addHandler(file_handler) +#console_handler = logging.StreamHandler(sys.stdout) +#console_handler.setFormatter(formatter) +#console_handler.setLevel(logging.DEBUG) +#app.logger.addHandler(console_handler) +#app.logger.setLevel(logging.DEBUG) + +@app.route('/') +def hello(): + return 'hello world' + +@app.route("/Marti/vcm", methods=[const.GET]) +def get_all_video_links(): + # This is called when the user selects the Download button in the Videos window. It + # expects an XML listing of all known feeds, so the user can pick and choose which ones + # to store locally + try: + feeds = dbController.query_videostream(column=["FullXmlString"]) + app.logger.info(f"Found {len(feeds)} video feeds in {const.DATABASE}") + if len(feeds) == 0: + return ("No video feeds found", 500) + all_feeds = "" + for feed in feeds: + # 'feed' is a tuple with one element, so we only append that + all_feeds += feed.FullXmlString.decode("utf-8") + return f"{all_feeds}" + except: + app.logger.error(traceback.format_exc()) + return "Error", 500 + + +@app.route("/Marti/vcm", methods=[const.POST]) +def insert_video_link(): + try: + xml_root = ET.fromstring(request.data.decode("utf-8")) + for xml_feed in xml_root: + protocol = xml_feed.find("protocol").text + alias = xml_feed.find("alias").text + uid = xml_feed.find("uid").text + address = xml_feed.find("address").text + port = xml_feed.find("port").text + rover_port = xml_feed.find("roverPort").text + ignore_klv = xml_feed.find("ignoreEmbeddedKLV").text + preferred_mac = xml_feed.find("preferredMacAddress").text + path = xml_feed.find("path").text + buf = xml_feed.find("buffer").text + timeout = xml_feed.find("timeout").text + rtsp_reliable = xml_feed.find("rtspReliable").text + # Check that no other feeds with the same UID have been received + streams = dbController.query_videostream(query=f'uid == "{uid}"') + if len(streams) > 0: + app.logger.info(f"Already received feed with UID={uid} (alias = {alias})") + continue # Ignore this feed if there are duplicates + app.logger.info(f"Inserting video feed into database: {request.data.decode('utf-8')}") + dbController.create_videostream(FullXmlString = ET.tostring(xml_feed), Protocol = protocol, Alias = alias, uid = uid, Address = address, Port = port, RoverPort=rover_port, IgnoreEmbeddedKlv=ignore_klv, PreferredMacAddress=preferred_mac, Path=path, Buffer=buf, Timeout=timeout, RtspReliable=rtsp_reliable) + + return "Okay", 200 + except: + app.logger.error(traceback.format_exc()) + return "Error", 500 + + +@app.route('/Marti/api/version/config', methods=[const.GET]) +def versionConfig(): + return const.VERSIONJSON + + +@app.route('/Marti/api/clientEndPoints', methods=[const.GET]) +def clientEndPoint(): + return const.versionInfo + + +@app.route('/Marti/sync/missionupload', methods=[const.POST]) +def upload(): + + file_hash = request.args.get('hash') + app.logger.info(f"Data Package hash = {str(file_hash)}") + letters = string.ascii_letters + uid = ''.join(random.choice(letters) for i in range(4)) + uid = 'uid-' + str(uid) + filename = request.args.get('filename') + creatorUid = request.args.get('creatorUid') + file = request.files.getlist('assetfile')[0] + directory = Path(dp_directory, file_hash) + if not Path.exists(directory): + os.mkdir(directory) + file.save(os.path.join(directory, filename)) + fileSize = Path(directory, filename).stat().st_size + callsign = str( + FlaskFunctions().getSubmissionUser(creatorUid, dbController)) # fetchone() gives a tuple, so only grab the first element + FlaskFunctions().create_dp(dbController, uid = uid, Name = filename, Hash = file_hash, SubmissionUser = callsign, CreatorUid = creatorUid, Size = fileSize) + return IP + ':' + str(HTTPPORT) + "/Marti/api/sync/metadata/" + file_hash + "/tool" + + +@app.route('/Marti/api/sync/metadata//tool', methods=[const.PUT]) +def putDataPackageTool(hash): + if request.data == b'private': + dbController.update_datapackage(query=f'Hash == "{hash}"', column_value={"Privacy": 1}) + return "Okay", 200 + + +@app.route('/Marti/api/sync/metadata//tool', methods=[const.GET]) +def getDataPackageTool(hash): + file_list = os.listdir(str(dp_directory) + '/' + str(hash)) + path = PurePath(dp_directory, str(hash), file_list[0]) + app.logger.info(f"Sending data package from {str(path)}") + return send_file(str(path)) + + +@app.route('/Marti/sync/search', methods=[const.GET]) +def retrieveData(): + keyword = request.args.get('keyword') + packages = FlaskFunctions().getAllPackages() + app.logger.info(f"Data packages in the database: {packages}") + return str(packages) + + +@app.route('/Marti/sync/content', methods=const.HTTPMETHODS) +def specificPackage(): + hash = request.args.get('hash') + app.logger.debug(os.listdir(str(dp_directory) + '/' + str(hash))) + file_list = os.listdir(str(dp_directory) + '/' + str(hash)) + app.logger.debug(const.DATAPACKAGEFOLDER + '\\' + hash + '\\' + file_list[0]) + path = PurePath(dp_directory, str(hash), file_list[0]) + app.logger.debug(str(path)) + return send_file(str(path)) + + +@app.route('/Marti/api/version', methods=[const.GET]) +def returnVersion(): + return const.versionInfo + + +@app.route('/Marti/sync/missionquery', methods=const.HTTPMETHODS) +def checkPresent(): + hash = request.args.get('hash') + if FlaskFunctions().hashIsPresent(hash, dbController): + app.logger.info(f"Data package with hash {hash} exists") + return IP + ':' + str(HTTPPORT) + "/Marti/api/sync/metadata/" + hash + "/tool" + else: + app.logger.info(f"Data package with hash {hash} does not exist") + return '404', 404 + +@app.route('/') +def home(): + return 'data package service is up, good job.' +class FlaskFunctions: + + def __init__(self): + self.callsigns = [] + + def create_dp(self, dbController, **args): + return dbController.create_datapackage(**args) + + def hashIsPresent(self, hash, dbControl): + data = dbControl.query_datapackage(query=f'Hash == "{hash}"') + return len(data) > 0 + + def getSubmissionUser(self, UID, dbControl): + callsign = dbControl.query_user(query=f'uid == "{UID}"', column=['callsign']) + return callsign + + def getAllPackages(self): + data = DatabaseController().query_datapackage() + package_dict = { + "resultCount": len(data), + "results": [] + } + for i in data: + package_dict["results"].append({ + "UID": i.uid, + "Name": i.Name, + "Hash": i.Hash, + "PrimaryKey": i.PrimaryKey, + "SubmissionDateTime": str(i.SubmissionDateTime.strftime("%Y-%m-%dT%H:%M:%S.%fZ")), + "SubmissionUser": i.SubmissionUser, + "CreatorUid": i.CreatorUid, + "Keywords": i.Keywords, + "MIMEType": i.MIMEType, + "Size": i.Size + }) + return package_dict + + def startup(self, ip, port): + try: + global IP, HTTPPORT + IP = ip + HTTPPORT = port + # Make sure the data package directory exists + if not Path(dp_directory).exists(): + app.logger.info(f"Creating directory at {str(dp_directory)}") + os.makedirs(str(dp_directory)) + # Create the relevant database tables + print(const.IP) + print(HTTPPORT) + app.run(host= ip, port=HTTPPORT, debug=const.HTTPDEBUG) + except Exception as e: + logger.error('there has been an exception in Data Package service startup ' + str(e)) + return -1 + + def stop(self): + func = request.environ.get('werkzeug.server.shutdown') + if func is None: + raise RuntimeError('Not running with the Werkzeug Server') + func() + +if __name__ == "__main__": + pass + diff --git a/FreeTAKServer/controllers/services/FTS.py b/FreeTAKServer/controllers/services/FTS.py new file mode 100644 index 00000000..890528f7 --- /dev/null +++ b/FreeTAKServer/controllers/services/FTS.py @@ -0,0 +1,351 @@ +import multiprocessing +import threading +import argparse +from FreeTAKServer.controllers.CreateStartupFilesController import CreateStartupFilesController +from FreeTAKServer.controllers.services.DataPackageServer import FlaskFunctions +from FreeTAKServer.controllers.configuration.OrchestratorConstants import OrchestratorConstants +from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants +from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController +from FreeTAKServer.controllers.services.RestAPI import RestAPI +from FreeTAKServer.model.ServiceObjects.FTS import FTS as FTSObj +from FreeTAKServer.model.SimpleClient import SimpleClient +import time +from FreeTAKServer.controllers.AddDataToCoTList import AddDataToCoTList +from FreeTAKServer.model.FilterGroup import FilterGroup +from FreeTAKServer.controllers.services.TCPCoTServiceController import TCPCoTServiceController +from FreeTAKServer.controllers.DatabaseControllers.DatabaseController import DatabaseController + +loggingConstants = LoggingConstants() +logger = CreateLoggerController("FTS").getLogger() + + +class FTS: + + def __init__(self): + self.CoTService = None + self.DataPackageService = None + self.UserCommand = None + self.killSwitch = False + self.ReceiveConnectionsReset = None + self.CoTPoisonPill = None + self.ClientDataPipe = None + self.clientArray = [] + self.socketCount = 0 + self.pipeList = {} + self.FilterGroup = FilterGroup() + self.FTSServiceStartupConfigObject = FTSObj() + self.dbController = DatabaseController() + logger.propagate = True + logger.info('something') + + def start_restAPI_service(self, StartupObjects): + try: + RestAPIPipe, self.RestAPIPipe = multiprocessing.Pipe(duplex=True) + self.RestAPICommands, self.RestAPICommandsFTS = multiprocessing.Pipe() + self.receive_Rest_stopper = threading.Event() + self.receive_Rest_stopper.clear() + self.receive_Rest = threading.Thread(target=self.receive_Rest_commands, args=(self.receive_Rest_stopper,)) + self.RestAPIProcess = multiprocessing.Process(target=RestAPI().startup, args=(RestAPIPipe, self.RestAPICommands, StartupObjects.RestAPIService.RestAPIServiceIP, StartupObjects.RestAPIService.RestAPIServicePort)) + self.receive_Rest.start() + self.RestAPIProcess.start() + self.pipeList['restAPI'] = self.RestAPIPipe + self.FilterGroup.sources.append(self.RestAPIPipe) + return 1 + except Exception as e: + logger.error('There has been an exception thrown in the startup of the restAPI service '+str(e)) + return -1 + + def stop_RestAPI_service(self): + try: + self.RestAPIProcess.terminate() + self.RestAPIProcess.join() + self.receive_Rest_stopper.set() + self.receive_Rest.join() + except Exception as e: + logger.error('an exception has been thrown in RestAPI Startup ' + str(e)) + + def start_CoT_service(self, FTSServiceStartupConfigObject): + try: + self.ClientDataPipe, ClientDataPipeParentChild = multiprocessing.Pipe() + ClientDataPipeParentChild.send('<__group role="Team Member" name="Yellow"/>') + print(self.ClientDataPipe.recv()) + self.TCPCoTService, self.TCPCoTServiceFTSPipe = multiprocessing.Pipe(duplex=True) + self.CoTPoisonPill = multiprocessing.Event() + self.CoTPoisonPill.set() + self.ReceiveConnectionsReset = multiprocessing.Event() + self.CoTService = multiprocessing.Process(target=TCPCoTServiceController().start, args=(FTSServiceStartupConfigObject.CoTService.CoTServiceIP, FTSServiceStartupConfigObject.CoTService.CoTServicePort, self.CoTPoisonPill, ClientDataPipeParentChild, self.ReceiveConnectionsReset, self.TCPCoTService)) + self.CoTService.start() + self.pipeList['TCPCoTServiceFTSPipe'] = self.TCPCoTServiceFTSPipe + self.FilterGroup.receivers.append(self.TCPCoTServiceFTSPipe) + self.FilterGroup.sources.append(self.TCPCoTServiceFTSPipe) + print('CoTService started') + return 1 + except Exception as e: + logger.error('an exception has been thrown in CoT service startup ' + str(e)) + return -1 + + def stop_CoT_service(self): + try: + self.ClientDataPipe.close() + self.CoTPoisonPill.clear() + + time.sleep(0.1) + if self.CoTService.is_alive(): + self.CoTService.terminate() + self.CoTService.join() + else: + self.CoTService.join() + + self.FilterGroup.sources.remove(self.TCPCoTServiceFTSPipe) + self.FilterGroup.receivers.remove(self.TCPCoTServiceFTSPipe) + + except Exception as e: + logger.error("there's been an exception in the stopping of CoT Service " + str(e)) + return -1 + return 1 + + def start_data_package_service(self, FTSServiceStartupConfigObject): + try: + print('start 213') + self.DataPackageService = multiprocessing.Process(target=FlaskFunctions().startup, + args=(FTSServiceStartupConfigObject.DataPackageService.DataPackageServiceIP, FTSServiceStartupConfigObject.DataPackageService.DataPackageServicePort)) + print('starting now') + self.DataPackageService.start() + time.sleep(2) + return 1 + except Exception as e: + logger.error('there has been an exception in the individual starting of the Data Packages Service ' + str(e)) + return -1 + + def stop_data_package_service(self): + try: + self.DataPackageService.terminate() + except Exception as e: + logger.error("there's been an exception in the termination of DataPackage Service " + str(e)) + return -1 + try: + self.DataPackageService.join() + except Exception as e: + logger.error("there's been an exception in the joining of DataPackage Service " + str(e)) + return -1 + return 1 + + #change object name to FTSServiceStartupConfigObject + def start_all(self, FTSServiceStartupConfigObject): + try: + self.FTSServiceStartupConfigObject = FTSServiceStartupConfigObject + if FTSServiceStartupConfigObject.DataPackageService.DataPackageServiceStatus == 'start': + self.start_data_package_service(FTSServiceStartupConfigObject) + + elif FTSServiceStartupConfigObject.DataPackageService.DataPackageServiceStatus == 'stop': + self.stop_data_package_service() + else: + pass + + if FTSServiceStartupConfigObject.CoTService.CoTServiceStatus == 'start': + self.start_CoT_service(FTSServiceStartupConfigObject) + + elif FTSServiceStartupConfigObject.CoTService.CoTServiceStatus == 'stop': + self.stop_CoT_service() + else: + pass + + return 1 + except Exception as e: + logger.error('there has been an exception in FTS start_all ' + str(e)) + return -1 + + def restart_receive_connection_process(self): + self.ReceiveConnectionsReset.set() + return 1 + + def receive_data_froCoT_service_thread(self, pipe, clientArray): + found = 0 + try: + if pipe.poll(timeout=0.01): + data = pipe.recv() + self.socketCount = data[2] + if data[0] == 'add': + clientArray.append(data[1]) + else: + for client in clientArray: + if client.ID == data[1].ID: + clientArray.remove(client) + found = 1 + else: + pass + if found == 0: + for client in clientArray: + if client.IP == data[1].IP and client.modelObject.detail.contact.callsign == data[1].modelObject.detail.contact.callsign: + clientArray.remove(client) + found = 1 + else: + pass + else: + pass + userData = self.show_users() + self.RestAPIPipe.send(userData) + return self.clientArray + else: + return self.clientArray + except Exception as e: + return self.clientArray + + def receive_Rest_commands(self, kill): + while kill.is_set() == False: + try: + command = self.RestAPICommandsFTS.recv() + function = getattr(self, command[0]) + if len(command)>=2: + output = function(command[1]) + else: + output = function() + self.RestAPICommandsFTS.send(output) + + except Exception as e: + logger.error('there has been an exception thrown in processing rest command ' + str(e)) + self.RestAPICommandsFTS.send('500') + + except Exception as e: + logger.error('there has been a critical exception ' + str(e)) + break + + def check_server_status(self): + return self.FTSServiceStartupConfigObject + + def show_users(self): + data = [['', '', '']] + objects = [] + output = [] + print(self.clientArray) + for client in self.clientArray: + data.append([client.IP, client.modelObject.detail.contact.callsign, client.modelObject.detail._group.name]) + for client in data: + simpleClient = SimpleClient() + simpleClient.callsign = client[1] + simpleClient.team = client[2] + simpleClient.ip = client[0] + objects.append(simpleClient) + + output.append('total sockets: '+str(self.socketCount)) + print(output) + return objects + + def verify_output(self, input, example=None): + try: + if example == None: + if input == None or input == -1: + return False + else: + return True + + else: + if isinstance(input, example): + return True + else: + return False + except Exception as e: + logger.error('there has been an exception in FTS verifying output ' + str(e)) + return False + + def stop_all(self): + try: + DataPackageServiceOutput = self.stop_data_package_service() + if self.verify_output(DataPackageServiceOutput): + pass + else: + raise Exception('error stopping DataPackage Service') + CoTServiceOutput = self.stop_CoT_service() + if self.verify_output(CoTServiceOutput): + pass + else: + raise Exception('error stopping CoT Service') + return 1 + except Exception as e: + logger.error('there has been an exception in FTS stop_all ' + str(e)) + return -1 + + def kill(self): + try: + self.killSwitch = True + return 1 + except Exception as e: + logger.error('error in kill function '+str(e)) + + def checkPipes(self): + try: + for pipe in self.FilterGroup.sources: + data = AddDataToCoTList().recv(pipe) + #this runs in the event a new client has connected + if isinstance(data, list): + AddDataToCoTList().send(self.FilterGroup.receivers, data[0]) + for client in self.clientArray: + AddDataToCoTList().send(self.FilterGroup.receivers, client) + # this runs in all other cases in which data is received + elif data != 0: + try: + print('data received in FTS ' + str(data.xmlString)) + except: + pass + AddDataToCoTList().send(self.FilterGroup.receivers, data) + # this runs when a timeout is triggered + else: + pass + except Exception as e: + pass + + def startup(self, CoTPort, CoTIP, DataPackagePort, DataPackageIP, RestAPIPort, RestAPIIP, AutoStart): + try: + if AutoStart == 'False': + StartupObject = FTSObj() + StartupObject.RestAPIService.RestAPIServicePort = RestAPIPort + StartupObject.RestAPIService.RestAPIServiceIP = RestAPIIP + self.start_restAPI_service(StartupObject) + + else: + StartupObject = FTSObj() + StartupObject.CoTService.CoTServiceIP = CoTIP + StartupObject.CoTService.CoTServicePort = CoTPort + StartupObject.CoTService.CoTServiceStatus = 'start' + + StartupObject.DataPackageService.DataPackageServiceIP = DataPackageIP + StartupObject.DataPackageService.DataPackageServicePort = DataPackagePort + StartupObject.DataPackageService.DataPackageServiceStatus = 'start' + + StartupObject.RestAPIService.RestAPIServicePort = RestAPIPort + StartupObject.RestAPIService.RestAPIServiceIP = RestAPIIP + StartupObject.RestAPIService.RestAPIServiceStatus = 'start' + + self.start_restAPI_service(StartupObject) + + self.start_all(StartupObject) + + + while True: + self.checkPipes() + self.clientArray = self.receive_data_froCoT_service_thread(self.ClientDataPipe, self.clientArray) + + except Exception as e: + logger.error('exception in the startup of FTS ' + str(e)) + +if __name__ == "__main__": + try: + parser = argparse.ArgumentParser(description=OrchestratorConstants().FULLDESC) + parser.add_argument('-CoTPort', type=int, help=OrchestratorConstants().COTPORTDESC, + default=FTSObj().CoTService.CoTServicePort) + parser.add_argument('-CoTIP', type=str, help=OrchestratorConstants().COTIPDESC, + default=FTSObj().CoTService.CoTServiceIP) + parser.add_argument('-DataPackagePort', type=int, help=OrchestratorConstants().APIPORTDESC, + default=FTSObj().DataPackageService.DataPackageServicePort) + parser.add_argument('-DataPackageIP', type=str, help=OrchestratorConstants().APIPORTDESC, + default=FTSObj().DataPackageService.DataPackageServiceIP) + parser.add_argument('-RestAPIPort', type=int, help=OrchestratorConstants().APIPORTDESC, + default=FTSObj().RestAPIService.RestAPIServicePort) + parser.add_argument('-RestAPIIP', type=str, help=OrchestratorConstants().APIPORTDESC, + default=FTSObj().RestAPIService.RestAPIServiceIP) + parser.add_argument('-AutoStart', type=str, help='wether or not you want all services to start or only the root service and the RestAPI service', default='True') + args = parser.parse_args() + CreateStartupFilesController() + FTS().startup(args.CoTPort, args.CoTIP, args.DataPackagePort, args.DataPackageIP, args.RestAPIPort, args.RestAPIIP, args.AutoStart) + except Exception as e: + print(e) \ No newline at end of file diff --git a/FreeTAKServer/controllers/services/Orchestrator.py b/FreeTAKServer/controllers/services/Orchestrator.py new file mode 100644 index 00000000..ce46d4c3 --- /dev/null +++ b/FreeTAKServer/controllers/services/Orchestrator.py @@ -0,0 +1,459 @@ +####################################################### +# +# orchestrator.py +# Python implementation of the Class orchestrator +# Generated by Enterprise Architect +# Created on: 21-May-2020 12:24:48 PM +# Original author: Natha Paquette +# +####################################################### +import os +from FreeTAKServer.controllers.ReceiveConnections import ReceiveConnections +from FreeTAKServer.controllers.ClientInformationController import ClientInformationController +from FreeTAKServer.controllers.ClientSendHandler import ClientSendHandler +from FreeTAKServer.controllers.SendClientData import SendClientData +from FreeTAKServer.controllers.DataQueueController import DataQueueController +from FreeTAKServer.controllers.ClientInformationQueueController import ClientInformationQueueController +from FreeTAKServer.controllers.ActiveThreadsController import ActiveThreadsController +from FreeTAKServer.controllers.ReceiveConnectionsProcessController import ReceiveConnectionsProcessController +from FreeTAKServer.controllers.MainSocketController import MainSocketController +from FreeTAKServer.controllers.XMLCoTController import XMLCoTController +from FreeTAKServer.controllers.SendDataController import SendDataController +from FreeTAKServer.controllers.AsciiController import AsciiController +from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants +from FreeTAKServer.controllers.configuration.DataPackageServerConstants import DataPackageServerConstants as DPConst +from FreeTAKServer.model.RawCoT import RawCoT +from FreeTAKServer.controllers.SpecificCoTControllers.SendDisconnectController import SendDisconnectController +from FreeTAKServer.controllers.configuration.OrchestratorConstants import OrchestratorConstants + +ascii = AsciiController().ascii +from logging.handlers import RotatingFileHandler +import logging +import multiprocessing +import importlib +import sqlite3 +import socket + +loggingConstants = LoggingConstants() + +from FreeTAKServer.controllers.ClientReceptionHandler import ClientReceptionHandler + + +class Orchestrator: + #TODO: fix repeat attempts to add user + # default constructor def __init__(self): + def __init__(self): + log_format = logging.Formatter(loggingConstants.LOGFORMAT) + self.logger = logging.getLogger(loggingConstants.LOGNAME) + self.logger.setLevel(logging.DEBUG) + self.logger.addHandler(self.newHandler(loggingConstants.DEBUGLOG, logging.DEBUG, log_format)) + self.logger.addHandler(self.newHandler(loggingConstants.WARNINGLOG, logging.WARNING, log_format)) + self.logger.addHandler(self.newHandler(loggingConstants.INFOLOG, logging.INFO, log_format)) + # create necessary queues + self.clientInformationQueue = [] + # this contains a list of all pipes which are transmitting CoT from clients + self.pipeList = [] + # Internal Pipe used for CoT generated by the server itself + self.internalCoTArray = [] + self.ClientReceptionHandlerEventPipe = '' + # health check events + self.healthCheckEventArray = [] + # instantiate controllers + self.ActiveThreadsController = ActiveThreadsController() + self.ClientInformationController = ClientInformationController() + self.ClientInformationQueueController = ClientInformationQueueController() + self.ClientSendHandler = ClientSendHandler() + self.DataQueueController = DataQueueController() + self.ReceiveConnections = ReceiveConnections() + self.ReceiveConnectionsProcessController = ReceiveConnectionsProcessController() + self.MainSocketController = MainSocketController() + self.XMLCoTController = XMLCoTController() + self.SendClientData = SendClientData() + self.KillSwitch = 0 + self.openSockets = 0 + self.openSocketsArray = [] + + def testing(self): + """ + function which creates variables for testing + """ + from multiprocessing import Pipe + from FreeTAKServer.controllers.DatabaseControllers.DatabaseController import DatabaseController + self.dbController = DatabaseController() + self.CoTSharePipe, other = Pipe() + return None + def newHandler(self, filename, log_level, log_format): + handler = RotatingFileHandler( + filename, + maxBytes=loggingConstants.MAXFILESIZE, + backupCount=loggingConstants.BACKUPCOUNT + ) + handler.setFormatter(log_format) + handler.setLevel(log_level) + return handler + + def sendUserConnectionGeoChat(self, clientInformation): + # TODO: refactor as it has a proper implementation of a PM to a user generated by the server + ''' + function to create and send pm to connecting user + :param clientInformation: + :return: + ''' + from FreeTAKServer.controllers.SpecificCoTControllers.SendGeoChatController import SendGeoChatController + from FreeTAKServer.model.RawCoT import RawCoT + from FreeTAKServer.model.FTSModel.Dest import Dest + import uuid + ChatObj = RawCoT() + ChatObj.xmlString = f'{OrchestratorConstants().DEFAULTCONNECTIONGEOCHATOBJ}' + classobj = SendGeoChatController(ChatObj) + instobj = classobj.getObject() + instobj.modelObject.detail._chat.chatgrp.setuid1(clientInformation.modelObject.uid) + dest = Dest() + dest.setcallsign(clientInformation.modelObject.detail.contact.callsign) + instobj.modelObject.detail.marti.setdest(dest) + instobj.modelObject.detail._chat.setchatroom(clientInformation.modelObject.detail.contact.callsign) + instobj.modelObject.detail._chat.setparent("RootContactGroup") + instobj.modelObject.detail._chat.setid(clientInformation.modelObject.uid) + instobj.modelObject.detail._chat.setgroupOwner("True") + instobj.modelObject.detail.remarks.setto(clientInformation.modelObject.uid) + instobj.modelObject.setuid('GeoChat.'+'SERVER-UID.'+clientInformation.modelObject.detail.contact.callsign+'.'+str(uuid.uuid1())) + instobj.modelObject.detail._chat.chatgrp.setid(clientInformation.modelObject.uid) + classobj.reloadXmlString() + SendDataController().sendDataInQueue(None, instobj, self.clientInformationQueue) + return 1 + + def clientConnected(self, rawConnectionInformation): + try: + # temporarily broken + # self.check_for_dead_sockets() + clientPipe = None + self.logger.info(loggingConstants.CLIENTCONNECTED) + clientInformation = self.ClientInformationController.intstantiateClientInformationModelFromConnection( + rawConnectionInformation, clientPipe) + if self.checkOutput(clientInformation): + pass + else: + raise Exception('error in the creation of client information') + self.openSockets += 1 + #breaks ssl + #self.ClientInformationQueueController.addClientToQueue(clientInformation) + self.clientInformationQueue.append(clientInformation) + try: + self.dbController.create_user(uid = clientInformation.modelObject.uid, callsign = clientInformation.modelObject.detail.contact.callsign) + except Exception as e: + self.logger.error( + 'there has been an error in a clients connection while adding information to the database ' + + str(e)) + self.logger.info(loggingConstants.CLIENTCONNECTEDFINISHED + str(clientInformation.modelObject.detail.contact.callsign)) + sock = clientInformation.socket + clientInformation.socket = None + self.clientDataPipe.send(['add', clientInformation, self.openSockets]) + clientInformation.socket = sock + self.sendUserConnectionGeoChat(clientInformation) + return clientInformation + except Exception as e: + self.logger.error(loggingConstants.CLIENTCONNECTEDERROR + str(e)) + return -1 + + def check_for_dead_sockets(self): + # fix function + try: + for sock in self.clientInformationQueue: + if sock.is_alive(): + pass + else: + self.clientDisconnected(sock) + return 1 + except Exception as e: + self.logger.error("there has been an exception in checking for dead sockets " + str(e)) + return -1 + + def emergencyReceived(self, processedCoT): + try: + if processedCoT.status == loggingConstants.ON: + self.internalCoTArray.append(processedCoT) + self.logger.debug(loggingConstants.EMERGENCYCREATED) + elif processedCoT.status == loggingConstants.OFF: + for CoT in self.internalCoTArray: + if CoT.type == "Emergency" and CoT.modelObject.uid == processedCoT.modelObject.uid: + self.internalCoTArray.remove(CoT) + self.logger.debug(loggingConstants.EMERGENCYREMOVED) + except Exception as e: + self.logger.error(loggingConstants.EMERGENCYRECEIVEDERROR + str(e)) + + def dataReceived(self, RawCoT): + # this will be executed in the event that the use case for the CoT isnt specified in the orchestrator + try: + # this will check if the CoT is applicable to any specific controllers + RawCoT = self.XMLCoTController.determineCoTType(RawCoT) + # the following calls whatever controller was specified by the above function + module = importlib.import_module('FreeTAKServer.controllers.SpecificCoTControllers.' + RawCoT.CoTType) + CoTSerializer = getattr(module, RawCoT.CoTType) + #TODO: improve way in which the dbController is passed to CoTSerializer + RawCoT.dbController = self.dbController + processedCoT = CoTSerializer(RawCoT).getObject() + sender = processedCoT.clientInformation + # this will send the processed object to a function which will send it to connected clients + try: + # TODO: method of determining if CoT should be added to the internal array should + # be improved + if processedCoT.type == "Emergency": + self.emergencyReceived(processedCoT) + else: + pass + except Exception as e: + return -1 + return processedCoT + except Exception as e: + self.logger.error(loggingConstants.DATARECEIVEDERROR + str(e)) + return -1 + + def sendInternalCoT(self, client): + try: + if len(self.internalCoTArray) > 0: + for processedCoT in self.internalCoTArray: + SendDataController().sendDataInQueue(processedCoT.clientInformation, processedCoT, [client]) + else: + pass + return 1 + except Exception as e: + self.logger.error(loggingConstants.MONITORRAWCOTERRORINTERNALSCANERROR + str(e)) + return -1 + + def clientDisconnected(self, clientInformation): + if hasattr(clientInformation, 'clientInformation'): + clientInformation = clientInformation.clientInformation + else: + pass + try: + self.openSockets -= 1 + socketa = clientInformation.socket + clientInformation.socket = None + self.clientDataPipe.send(['remove', clientInformation, self.openSockets]) + clientInformation.socket = socketa + try: + clientInformation.socket.shutdown(socket.SHUT_RDWR) + except Exception as e: + self.logger.error('error shutting socket down in client disconnection') + pass + try: + clientInformation.socket.close() + except Exception as e: + self.logger.error('error closing socket in client disconnection') + pass + + self.logger.info(loggingConstants.CLIENTDISCONNECTSTART) + for client in self.clientInformationQueue: + if client.ID == clientInformation.ID: + self.clientInformationQueue.remove(client) + else: + pass + try: + self.ActiveThreadsController.removeClientThread(clientInformation) + self.dbController.remove_user(query=f"uid == {clientInformation.modelObject.uid}") + except Exception as e: + self.logger.error('there has been an error in a clients disconnection while adding information to the database') + pass + # TODO: remove string + tempXml = RawCoT() + tempXml.xmlString = ''.format(clientInformation.modelObject.uid).encode() + disconnect = SendDisconnectController(tempXml) + SendDataController().sendDataInQueue(disconnect.getObject().clientInformation, disconnect.getObject(), self.clientInformationQueue, self.CoTSharePipe) + self.logger.info(loggingConstants.CLIENTDISCONNECTEND + str(clientInformation.modelObject.detail.contact.callsign)) + return 1 + except Exception as e: + self.logger.error(loggingConstants.CLIENTCONNECTEDERROR + " " + str(e)) + pass + + def monitorRawCoT(self,data): + # this needs to be the most robust function as it is the keystone of the program + # this will attempt to define the type of CoT along with the designated controller + try: + CoT = XMLCoTController().determineCoTGeneral(data) + function = getattr(self, CoT[0]) + output = function(CoT[1]) + return output + except Exception as e: + self.logger.error(loggingConstants.MONITORRAWCOTERRORB + str(e)) + return -1 + + def checkOutput(self, output): + if output != -1 and output != None: + return True + else: + return False + + def loadAscii(self): + ascii() + + def mainRunFunction(self, clientData, receiveConnection, sock, pool, event, clientDataPipe, ReceiveConnectionKillSwitch, CoTSharePipe): + print('server started') + while True: + self.CoTSharePipe = CoTSharePipe + try: + self.clientDataPipe = clientDataPipe + if event.is_set(): + try: + if ReceiveConnectionKillSwitch.is_set(): + try: + receiveConnection.successful() + except: + pass + ReceiveConnectionKillSwitch.clear() + receiveConnection = pool.apply_async(ReceiveConnections().listen, + (sock,)) + else: + receiveConnectionOutput = receiveConnection.get(timeout=0.01) + receiveConnection = pool.apply_async(ReceiveConnections().listen, (sock,)) + CoTOutput = self.handel_connection_data(receiveConnectionOutput) + + except multiprocessing.TimeoutError: + pass + except Exception as e: + self.logger.error('exception in receive connection within main run function '+str(e)) + + try: + clientDataOutput = clientData.get(timeout=0.01) + if self.checkOutput(clientDataOutput) and isinstance(clientDataOutput, list): + CoTOutput = self.handel_regular_data(clientDataOutput) + else: + raise Exception('client reception handler has returned data which is not of type list data is ' + str(clientDataOutput)) + clientData = pool.apply_async(ClientReceptionHandler().startup, (self.clientInformationQueue,)) + except multiprocessing.TimeoutError: + pass + except Exception as e: + self.logger.info('exception in receive client data within main run function ' + str(e)) + pass + try: + if CoTSharePipe.poll(timeout=0.1): + data = CoTSharePipe.recv() + CoTOutput = self.handel_shared_data(data) + else: + pass + except Exception as e: + self.logger.error('there has been an excepion in the handling of data supplied by the rest API '+str(e)) + pass + else: + self.stop() + break + except Exception as e: + self.logger.info('there has been an uncaught error thrown in mainRunFunction' + str(e)) + pass + + def handel_shared_data(self, modelData): + try: + print('data received within orchestrator '+str(modelData.xmlString)) + if hasattr(modelData, 'clientInformation'): + output = SendDataController().sendDataInQueue(modelData.clientInformation, modelData, + self.clientInformationQueue) + # + + elif modelData.type == "connmessage": + self.internalCoTArray.append(modelData) + + # this runs in the event of a new connection + else: + output = SendDataController().sendDataInQueue(None, modelData, + self.clientInformationQueue) + except Exception as e: + print(e) + + def handel_regular_data(self, clientDataOutput): + try: + for clientDataOutputSingle in clientDataOutput: + try: + print('handling reg data') + CoTOutput = self.monitorRawCoT(clientDataOutputSingle) + if CoTOutput == 1: + continue + elif self.checkOutput(CoTOutput): + output = SendDataController().sendDataInQueue(CoTOutput.clientInformation, CoTOutput, + self.clientInformationQueue, self.CoTSharePipe) + if self.checkOutput(output) and isinstance(output, tuple) == False: + pass + elif isinstance(output, tuple): + self.logger.error('issue sending data to client now disconnecting') + self.clientDisconnected(output[1]) + + else: + self.logger.error('send data failed in main run function with data ' + str( + CoTOutput.xmlString) + ' from client ' + CoTOutput.clientInformation.modelObject.detail.contact.callsign) + + else: + raise Exception('error in general data processing') + except Exception as e: + self.logger.info( + 'exception in client data, data processing within main run function ' + str( + e) + ' data is ' + str(CoTOutput)) + pass + except Exception as e: + self.logger.info( + 'exception in client data, data processing within main run function ' + str( + e) + ' data is ' + str(clientDataOutput)) + except Exception as e: + self.logger.info("there has been an error iterating client data output " + str(e)) + return -1 + return 1 + + def handel_connection_data(self, receiveConnectionOutput): + try: + print('handling conn data') + CoTOutput = self.monitorRawCoT(receiveConnectionOutput) + if CoTOutput != -1 and CoTOutput != None: + output = SendDataController().sendDataInQueue(CoTOutput, CoTOutput, + self.clientInformationQueue, self.CoTSharePipe) + if self.checkOutput(output): + self.logger.debug('connection data from client ' + str( + CoTOutput.modelObject.detail.contact.callsign) + ' successfully processed') + else: + raise Exception('error in sending data') + else: + raise Exception('error in connection data processing') + except Exception as e: + self.logger.error('exception in receive connection data processing within main run function ' + str( + e) + ' data is ' + str(CoTOutput)) + return -1 + self.sendInternalCoT(CoTOutput) + return 1 + + def start(self, IP, CoTPort, Event, clientDataPipe, ReceiveConnectionKillSwitch, RestAPIPipe): + try: + self.db = sqlite3.connect(DPConst().DATABASE) + os.chdir('../../../') + # create socket controller + self.MainSocketController.changeIP(IP) + self.MainSocketController.changePort(CoTPort) + sock = self.MainSocketController.createSocket() + #changed + from multiprocessing.pool import ThreadPool + pool = ThreadPool(processes=2) + self.pool = pool + clientData = pool.apply_async(ClientReceptionHandler().startup, (self.clientInformationQueue,)) + receiveConnection = pool.apply_async(ReceiveConnections().listen, (sock,)) + # instantiate domain model and save process as object + self.mainRunFunction(clientData, receiveConnection, sock, pool, Event, clientDataPipe, ReceiveConnectionKillSwitch, RestAPIPipe) + + except Exception as e: + self.logger.critical('there has been a critical error in the startup of FTS' + str(e)) + return -1 + + def stop(self): + self.clientDataPipe.close() + self.pool.terminate() + self.pool.close() + self.pool.join() + + + +"""if __name__ == "__main__": + + parser = argparse.ArgumentParser(description=OrchestratorConstants().FULLDESC) + parser.add_argument(OrchestratorConstants().COTPORTARG, type=int, help=OrchestratorConstants().COTPORTDESC, + default=OrchestratorConstants().COTPORT) + parser.add_argument(OrchestratorConstants().IPARG, type=str, help=OrchestratorConstants().IPDESC, + default=OrchestratorConstants().IP) + parser.add_argument(OrchestratorConstants().APIPORTARG, type=int, help=OrchestratorConstants().APIPORTDESC, + default=DataPackageServerConstants().APIPORT) + args = parser.parse_args() + CreateStartupFilesController() + Orchestrator().start(args.IP, args.CoTPort, args.APIPort)""" \ No newline at end of file diff --git a/FreeTAKServer/controllers/services/RestAPI.py b/FreeTAKServer/controllers/services/RestAPI.py new file mode 100644 index 00000000..2a709e53 --- /dev/null +++ b/FreeTAKServer/controllers/services/RestAPI.py @@ -0,0 +1,275 @@ +from flask import Flask, request, jsonify +from flask_sqlalchemy import SQLAlchemy +from flask_socketio import SocketIO, emit +import threading +from lxml import etree +from FreeTAKServer.model.FTSModel.Event import Event +from FreeTAKServer.model.RawCoT import RawCoT +from FreeTAKServer.controllers.ApplyFullJsonController import ApplyFullJsonController +from FreeTAKServer.controllers.XMLCoTController import XMLCoTController +from FreeTAKServer.model.ServiceObjects.FTS import FTS +from FreeTAKServer.controllers.configuration.RestAPIVariables import RestAPIVariables as vars +from FreeTAKServer.model.SimpleClient import SimpleClient +from FreeTAKServer.controllers.DatabaseControllers.DatabaseController import DatabaseController +from FreeTAKServer.controllers.configuration.DatabaseConfiguration import DatabaseConfiguration + +import os +import shutil +import json +from flask_cors import CORS + +dbController = DatabaseController() + +UpdateArray = [] + +functionNames = vars() +functionNames.function_names() + +jsonVars = vars() +jsonVars.json_vars() + +restMethods = vars() +restMethods.rest_methods() + +defaultValues = vars() +defaultValues.default_values() + +app = Flask(__name__) +app.config['SQLALCHEMY_DATABASE_URI'] = DatabaseConfiguration().DataBaseConnectionString +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False +db = SQLAlchemy(app) +dbController.session = db.session +CORS(app) +socketio = SocketIO(app, async_handlers=True, async_mode="threading") +socketio.init_app(app, cors_allowed_origins="*") +APIPipe = None +CommandPipe = None +app.config["SECRET_KEY"] = 'vnkdjnfjknfl1232#' + + +@app.route('/') +def sessions(): + return b'working' + +@socketio.on('connect') +def handle_message(): + emit('data', json.dumps({'abc234': 'test123'})) + +@socketio.on('Update') +def handel_updates(msg): + print(msg) + emitUpdatesThread = threading.Thread(target=emitUpdates, args=(APIPipe,), daemon=True) + emitUpdatesThread.start() + emitUpdatesThread.join() + +@app.route("/SendGeoChat", methods=[restMethods.POST]) +def SendGeoChat(): + try: + json = request.json + modelObject = Event.GeoChat() + out = ApplyFullJsonController().serializeJsonToModel(modelObject, json) + xml = XMLCoTController().serialize_model_to_CoT(out, 'event') + from FreeTAKServer.controllers.SpecificCoTControllers.SendGeoChatController import SendGeoChatController + rawcot = RawCoT() + rawcot.xmlString = xml + rawcot.clientInformation = None + object = SendGeoChatController(rawcot) + APIPipe.send(object.getObject()) + return '200', 200 + except Exception as e: + print(e) + +@app.route("/ConnectionMessage", methods=[restMethods.POST]) +def ConnectionMessage(): + try: + json = request.json + modelObject = Event.GeoChat() + out = ApplyFullJsonController().serializeJsonToModel(modelObject, json) + xml = XMLCoTController().serialize_model_to_CoT(out, 'event') + from FreeTAKServer.controllers import SendGeoChatController + rawcot = RawCoT() + rawcot.xmlString = xml + rawcot.clientInformation = None + object = SendGeoChatController(rawcot).getObject() + object.type = "connmessage" + APIPipe.send(object.SendGeoChat) + return '200', 200 + except Exception as e: + print(e) + +@app.route("/RecentCoT", methods=[restMethods.GET]) +def RecentCoT(): + return b'1234' + +@app.route("/URL", methods=[restMethods.GET]) +def URLGET(): + data = request.args + print(data) + return 'completed', 200 + +@app.route("/Clients", methods=[restMethods.GET]) +def Clients(): + try: + CommandPipe.send([functionNames.Clients]) + out = CommandPipe.recv() + returnValue = [] + for client in out: + returnValue.append(ApplyFullJsonController().serialize_model_to_json(client)) + return json.dumps(returnValue) + except Exception as e: + return str(e), 500 + +@app.route('/DataPackageTable', methods=[restMethods.GET, restMethods.POST, "DELETE"]) +def DataPackageTable(): + if request.method == "GET": + output = dbController.query_datapackage() + for i in range(0, len(output)): + output[i] = output[i].__dict__ + del(output[i]['_sa_instance_state']) + del(output[i]['CreatorUid']) + del(output[i]['Hash']) + del(output[i]['MIMEType']) + del(output[i]['uid']) + return jsonify(json_list = output), 200 + + elif request.method == "DELETE": + Hash = request.args.get('Hash') + obj = dbController.query_datapackage(f'PrimaryKey == "{Hash}"') + dbController.remove_datapackage(f'PrimaryKey == "{Hash}"') + # TODO: make this coherent with constants + currentPath = os.path.dirname(os.path.realpath(__file__)) + shutil.rmtree(f'{str(currentPath)}/FreeTAKServerDataPackageFolder/{obj[0].Hash}') + return '200', 200 + +@app.route('/checkStatus', methods=[restMethods.GET]) +def check_status(): + try: + CommandPipe.send([functionNames.checkStatus]) + FTSServerStatusObject = CommandPipe.recv() + out = ApplyFullJsonController().serialize_model_to_json(FTSServerStatusObject) + return json.dumps(out), 200 + except Exception as e: + return str(e), 500 + +@app.route('/changeStatus', methods=[restMethods.POST]) +def All(): + try: + FTSObject = FTS() + if request.method == restMethods.POST: + json = request.json + if jsonVars.COTSERVICE in json: + CoTService = json[jsonVars.COTSERVICE] + FTSObject.CoTService.CoTServiceIP = CoTService.get(jsonVars.IP) + try: + FTSObject.CoTService.CoTServicePort = int(CoTService.get(jsonVars.PORT)) + except: + FTSObject.CoTService.CoTServicePort = '' + FTSObject.CoTService.CoTServiceStatus = CoTService.get(jsonVars.STATUS) + else: + pass + if jsonVars.DATAPACKAGESERVICE in json: + + DPService = json.get(jsonVars.DATAPACKAGESERVICE) + FTSObject.DataPackageService.DataPackageServiceIP = DPService.get(jsonVars.IP) + try: + FTSObject.DataPackageService.DataPackageServicePort = int(DPService.get(jsonVars.PORT)) + except: + FTSObject.DataPackageService.DataPackageServicePort = '' + FTSObject.DataPackageService.DataPackageServiceStatus = DPService.get(jsonVars.STATUS) + + else: + pass + + CommandPipe.send([functionNames.Status, FTSObject]) + out = CommandPipe.recv() + return '200', 200 + + except Exception as e: + return '500', 500 + +def receiveUpdates(): + while True: + try: + update = APIPipe.recv() + global UpdateArray + UpdateArray.append(update) + print(UpdateArray) + except Exception as e: + print(e) + +def submitData(dataRaw): + global APIPipe + print(APIPipe) + data = RawCoT() + data.clientInformation = "SERVER" + data.xmlString = dataRaw.encode() + APIPipe.send([data]) + +def emitUpdates(Updates): + data = [SimpleClient()] + data[0].callsign = '' + data[0].team = '' + data[0].ip = '' + returnValue = [] + for client in data: + returnValue.append(ApplyFullJsonController().serialize_model_to_json(client)) + socketio.emit('up', json.dumps(returnValue)) + while True: + try: + for _ in UpdateArray: + returnValue = [] + print(UpdateArray) + data = UpdateArray.pop(0) + for client in data: + returnValue.append(ApplyFullJsonController().serialize_model_to_json(client)) + socketio.emit('up', json.dumps(returnValue)) + socketio.sleep(0.1) + except Exception as e: + print(e) + pass + +def test(json): + modelObject = Event.dropPoint() + out = XMLCoTController().serialize_CoT_to_model(modelObject, etree.fromstring(json)) + xml = XMLCoTController().serialize_model_to_CoT(out, 'event') + from FreeTAKServer.controllers.SpecificCoTControllers.SendDropPointController import SendDropPointController + rawcot = RawCoT() + rawcot.xmlString = xml + rawcot.clientInformation = None + object = SendDropPointController(rawcot) + print(etree.tostring(object.sendDropPoint.xmlString,pretty_print=True).decode()) + '''EventObject = json + modelObject = ApplyFullJsonController(json, 'Point', modelObject).determine_function() + out = XMLCoTController().serialize_model_to_CoT(modelObject, 'event') + print(etree.tostring(out)) + print(RestAPI().serializeJsonToModel(modelObject, EventObject))''' + + + +class RestAPI: + def __init__(self): + pass + + def startup(self, APIPipea, CommandPipea, IP, Port): + global APIPipe, CommandPipe + APIPipe = APIPipea + CommandPipe = CommandPipea + threading.Thread(target=receiveUpdates, daemon=True, args=()).start() + + socketio.run(app, host=IP, port=Port, debug=True, use_reloader=False) + + + def serializeJsonToModel(self, model, Json): + for key, value in Json.items(): + if isinstance(value, dict): + submodel = getattr(model, key) + out = self.serializeJsonToModel(submodel, value) + setattr(model, key, out) + else: + setattr(model, key, value) + return model + +if __name__ == '__main__': + RestAPI().startup() + # app.run(host="127.0.0.1", port=80) + diff --git a/FreeTAKServer/controllers/services/TCPCoTServiceController.py b/FreeTAKServer/controllers/services/TCPCoTServiceController.py new file mode 100644 index 00000000..f9baf1a5 --- /dev/null +++ b/FreeTAKServer/controllers/services/TCPCoTServiceController.py @@ -0,0 +1,36 @@ +from FreeTAKServer.controllers.services.Orchestrator import Orchestrator +from FreeTAKServer.controllers.ClientReceptionHandler import ClientReceptionHandler +from FreeTAKServer.controllers.ReceiveConnections import ReceiveConnections +from FreeTAKServer.controllers.TCPSocketController import TCPSocketController +import os +from multiprocessing.pool import ThreadPool +from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants +from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController +from FreeTAKServer.controllers.DatabaseControllers.DatabaseController import DatabaseController +loggingConstants = LoggingConstants() +logger = CreateLoggerController("FTS").getLogger() + +class TCPCoTServiceController(Orchestrator): + def start(self, IP, CoTPort, Event, clientDataPipe, ReceiveConnectionKillSwitch, RestAPIPipe): + try: + self.dbController = DatabaseController() + clientDataPipe.send( + '<__group role="Team Member" name="Yellow"/>') + + os.chdir('../../../') + # create socket controller + self.TCPSocketController = TCPSocketController() + self.TCPSocketController.changeIP(IP) + self.TCPSocketController.changePort(CoTPort) + sock = self.TCPSocketController.createSocket() + pool = ThreadPool(processes=2) + self.pool = pool + clientData = pool.apply_async(ClientReceptionHandler().startup, (self.clientInformationQueue,)) + receiveConnection = pool.apply_async(ReceiveConnections().listen, (sock,)) + # instantiate domain model and save process as object + self.mainRunFunction(clientData, receiveConnection, sock, pool, Event, clientDataPipe, + ReceiveConnectionKillSwitch, RestAPIPipe) + except Exception as e: + logger.error('there has been an exception in the start function ' + 'of TCPCoTService ' + str(e)) + return e diff --git a/FreeTAKServer/controllers/services/__init__.py b/FreeTAKServer/controllers/services/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/controllers/statusCheck.py b/FreeTAKServer/controllers/statusCheck.py index f6a3fdd9..eec7de6f 100644 --- a/FreeTAKServer/controllers/statusCheck.py +++ b/FreeTAKServer/controllers/statusCheck.py @@ -1,7 +1,7 @@ import socket from time import sleep, gmtime, strftime import uuid -import smtplib, ssl +import smtplib import time class statusCheck: diff --git a/FreeTAKServer/model/ActiveThreads.py b/FreeTAKServer/model/ActiveThreads.py new file mode 100644 index 00000000..f8a065e0 --- /dev/null +++ b/FreeTAKServer/model/ActiveThreads.py @@ -0,0 +1,15 @@ +####################################################### +# +# ActiveThreads.py +# Python implementation of the Class ActiveThreads +# Generated by Enterprise Architect +# Created on: 21-May-2020 10:18:14 AM +# Original author: Natha Paquette +# +####################################################### + + +class ActiveThreads: +# default constructor def __init__(self): + + ThreadArray = [] diff --git a/FreeTAKServer/model/ClientInformation.py b/FreeTAKServer/model/ClientInformation.py new file mode 100644 index 00000000..dba90645 --- /dev/null +++ b/FreeTAKServer/model/ClientInformation.py @@ -0,0 +1,36 @@ +####################################################### +# +# ClientInformation.py +# Python implementation of the Class ClientInformation +# Generated by Enterprise Architect +# Created on: 21-May-2020 9:47:19 AM +# Original author: Natha Paquette +# +####################################################### +import copy + +class ClientInformation: + def __init__(self): + self.modelObject = '' + self.alive = "" + self.dataQueue = "" + self.ID = "" + self.idData = "" + self.IP = "" + self.receptionHandler = "" + self.sendData = "" + self.socket = "" + self.type = "clientInformation" + + def __deepcopy__(self, memodict={}): + returned = ClientInformation() + returned.modelObject = copy.deepcopy(self.modelObject) + returned.alive = copy.deepcopy(self.alive) + returned.dataQueue = copy.deepcopy(self.dataQueue) + returned.ID = copy.deepcopy(self.ID) + returned.idData = copy.deepcopy(self.idData) + returned.IP = copy.deepcopy(self.IP) + returned.receptionHandler = copy.deepcopy(self.receptionHandler) + returned.sendData = copy.deepcopy(self.sendData) + returned.type = copy.deepcopy(self.type) + return returned \ No newline at end of file diff --git a/FreeTAKServer/model/ClientInformationQueue.py b/FreeTAKServer/model/ClientInformationQueue.py new file mode 100644 index 00000000..c6da14bd --- /dev/null +++ b/FreeTAKServer/model/ClientInformationQueue.py @@ -0,0 +1,15 @@ +####################################################### +# +# ClientInformationQueue.py +# Python implementation of the Class ClientInformationQueue +# Generated by Enterprise Architect +# Created on: 21-May-2020 9:47:34 AM +# Original author: Natha Paquette +# +####################################################### +from multiprocessing import Queue + +class ClientInformationQueue: + def __init__(self): + + self.clientQueue = Queue() \ No newline at end of file diff --git a/FreeTAKServer/model/DataQueue.py b/FreeTAKServer/model/DataQueue.py new file mode 100644 index 00000000..cf83fa8d --- /dev/null +++ b/FreeTAKServer/model/DataQueue.py @@ -0,0 +1,15 @@ +####################################################### +# +# DataQueue.py +# Python implementation of the Class DataQueue +# Generated by Enterprise Architect +# Created on: 21-May-2020 9:47:23 AM +# Original author: Natha Paquette +# +####################################################### + + +class DataQueue: +# default constructor def __init__(self): + + __dataArray = "" \ No newline at end of file diff --git a/FreeTAKServer/model/DestList.py b/FreeTAKServer/model/DestList.py new file mode 100644 index 00000000..87cd60d4 --- /dev/null +++ b/FreeTAKServer/model/DestList.py @@ -0,0 +1,9 @@ +class DestList: + def __init__(self): + self.destList = [] + + def getDestList(self): + return self.destList + + def setDestList(self, destList): + self.destList = destList \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/Archive.py b/FreeTAKServer/model/FTSModel/Archive.py new file mode 100644 index 00000000..25185a5a --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Archive.py @@ -0,0 +1,7 @@ +class Archive: + def __init__(self): + pass + + @staticmethod + def drop_point(): + pass \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/Chat.py b/FreeTAKServer/model/FTSModel/Chat.py new file mode 100644 index 00000000..80483f8c --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Chat.py @@ -0,0 +1,92 @@ +####################################################### +# +# __chat.py +# Python implementation of the Class __chat +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:10 AM +# Original author: Corvo +# +####################################################### +from FreeTAKServer.model.FTSModelVariables.ChatVariables import ChatVariables as vars +from FreeTAKServer.model.FTSModel.Chatgrp import Chatgrp + +class Chat: + # default constructor + def __init__(self): + self.senderCallsign = None + self.id = None + self.parent = None + self.chatroom = None + self.groupOwner = None + self.chatgrp = None + + @staticmethod + def geochat(GROUPOWNER = vars.geochat().GROUPOWNER, ID = vars.geochat().ID, PARENT = vars.geochat().PARENT, + CHATROOM = vars.geochat().CHATROOM, SENDERCALLSIGN = vars.geochat().SENDERCALLSIGN): + chat = Chat() + chat.setgroupOwner(GROUPOWNER) + chat.setparent(PARENT) + chat.setid(ID) + chat.setchatroom(CHATROOM) + chat.setsenderCallsign(SENDERCALLSIGN) + chat.setchatgrp(Chatgrp.geochat()) + return chat + + def getparent(self): + return self.parent + + # parent setter + def setparent(self,parent=0): + self.parent=parent + + # senderCallsign getter + def getsenderCallsign(self): + return senderCallsign + + # senderCallsign setter + def setsenderCallsign(self,senderCallsignn): + global senderCallsign + senderCallsign=senderCallsignn + + # chatroom getter + def getchatroom(self): + return self.chatroom + + # chatroom setter + def setchatroom(self, chatroom=0): + self.chatroom=chatroom + + # groupOwner getter + def getgroupOwner(self): + return self.groupOwner + + # groupOwner setter + def setgroupOwner(self, groupOwner=0): + self.groupOwner=groupOwner + + # id getter + def getid(self): + return self.id + + # id setter + def setid(self, id=0): + self.id=id + #chatgrp uid0 getter + def getuid0(self): + self.chatgrp().getuid0() + + def setuid0(self, uid0=0): + self.chatgrp().setuid0(uid0) + + def getuid1(self): + self.chatgrp().getuid1() + + def setuid1(self, uid1=0): + self.chatgrp().setuid1(uid1) + + def getchatgrp(self): + return self.chatgrp + + def setchatgrp(self, chatgrp=0): + print(chatgrp) + self.chatgrp = chatgrp diff --git a/FreeTAKServer/model/FTSModel/Chatgrp.py b/FreeTAKServer/model/FTSModel/Chatgrp.py new file mode 100644 index 00000000..d17a242c --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Chatgrp.py @@ -0,0 +1,64 @@ +####################################################### +# +# chatgrp.py +# Python implementation of the Class chatgrp +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:10 AM +# Original author: Corvo +# +####################################################### +from FreeTAKServer.model.FTSModelVariables.ChatgrpVariables import ChatgrpVariables as vars + +class Chatgrp: + def __init__(self): + self.uid0 = None + self.uid1 = None + self.id = None + + @staticmethod + def geochat(UID0 = vars.geochat().UID0, UID1 = vars.geochat().UID1, ID = vars.geochat().ID): + chatgrp = Chatgrp() + chatgrp.setid(ID) + chatgrp.setuid0(UID0) + chatgrp.setuid1(UID1) + return chatgrp + + def chatToTeamFunc(self, uid0, uid1, id): + self.setuid0(uid0) + self.setuid1(uid1) + self.setid(id) + + def chatToGroupFunc(self, uid0, uid1, id): + self.setuid0(uid0) + self.setuid1(uid1) + self.setid(id) + + def chatToAllFunc(self, uid0, uid1, id): + self.setuid0(uid0) + self.setuid1(uid1) + self.setid(id) + + def getuid0(self): + return self.uid0 + + # uid0 setter + def setuid0(self, uid0=0): + self.uid0=uid0 + + # uid1 getter + def getuid1(self): + return self.uid1 + + # uid1 setter + def setuid1(self, uid1=0): + self.uid1=uid1 + + # id getter + def getid(self): + return self.id + + # id setter + def setid(self, id=0): + self.id=id + + diff --git a/FreeTAKServer/model/FTSModel/Color.py b/FreeTAKServer/model/FTSModel/Color.py new file mode 100644 index 00000000..160a6a2a --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Color.py @@ -0,0 +1,28 @@ +####################################################### +# +# color.py +# Python implementation of the Class color +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:07 AM +# Original author: Corvo +# +####################################################### +from FreeTAKServer.model.FTSModelVariables.ColorVariables import ColorVariables as vars + +class Color: + def __init__(self): + self.argb = None + + @staticmethod + def drop_point(ARGB = vars.drop_point().ARGB): + color = Color() + color.setargb(ARGB) + return color + + # argb getter + def getargb(self): + return self.argb + + # argb setter + def setargb(self, argb=0): + self.argb=argb diff --git a/FreeTAKServer/model/FTSModel/Contact.py b/FreeTAKServer/model/FTSModel/Contact.py new file mode 100644 index 00000000..bad115a3 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Contact.py @@ -0,0 +1,117 @@ +####################################################### +# +# Contact.py +# Python implementation of the Class Contact +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:08 AM +# Original author: Corvo +# +####################################################### +from FreeTAKServer.model.FTSModelVariables.ContactVariables import ContactVariables as vars + +class Contact: + def __init__(self): + self.callsign = None + self.endpoint = None + self.iconsetpath = None + self.uid = None + self.name = None + + @staticmethod + def drop_point(CALLSIGN = vars.drop_point().CALLSIGN): + contact = Contact() + contact.setcallsign(callsign=CALLSIGN) + return contact + + @staticmethod + def connection(CALLSIGN = vars.connection().CALLSIGN, ENDPOINT = vars.connection().ENDPOINT, + ICONSETPATH = vars.connection().ICONSETPATH,UID = vars.connection().UID, + NAME = vars.connection().NAME): + + contact = Contact() + contact.setcallsign(CALLSIGN) + contact.setname(NAME) + contact.setuid(UID) + contact.setendpoint(ENDPOINT) + contact.seticonsetpath(ICONSETPATH) + return contact + + @staticmethod + def geochat(CALLSIGN=vars.geochat().CALLSIGN, ENDPOINT=vars.geochat().ENDPOINT, + ICONSETPATH=vars.geochat().ICONSETPATH, UID=vars.geochat().UID, + NAME=vars.geochat().NAME): + contact = Contact() + contact.setcallsign(CALLSIGN) + contact.setname(NAME) + contact.setuid(UID) + contact.setendpoint(ENDPOINT) + contact.seticonsetpath(ICONSETPATH) + return contact + + @staticmethod + def emergency_on(CALLSIGN=vars.emergency_on().CALLSIGN, ENDPOINT=vars.emergency_on().ENDPOINT, + ICONSETPATH=vars.emergency_on().ICONSETPATH, UID=vars.emergency_on().UID, + NAME=vars.emergency_on().NAME): + contact = Contact() + contact.setcallsign(CALLSIGN) + contact.setname(NAME) + contact.setuid(UID) + contact.setendpoint(ENDPOINT) + contact.seticonsetpath(ICONSETPATH) + return contact + + @staticmethod + def UserUpdate(ENDPOINT=vars.UserUpdate().endpoint, PHONE=vars.UserUpdate().phone, + CALLSIGN=vars.UserUpdate().callsign): + contact = Contact() + contact.setendpoint(ENDPOINT) + contact.setphone(PHONE) + contact.setcallsign(CALLSIGN) + return contact + + # iconsetpath getter + def geticonsetpath(self): + return self.iconsetpath + + # iconsetpath setter + def seticonsetpath(self, iconsetpath=None): + self.iconsetpath=iconsetpath + + # callsign getter + def getcallsign(self): + return self.callsign + + # callsign setter + def setcallsign(self, callsign=None): + self.callsign=callsign + + + # endpoint getter + def getendpoint(self): + return self.endpoint + + # endpoint setter + def setendpoint(self, endpoint=None): + self.endpoint=endpoint + + def getuid(self): + return self.uid + + # uid setter + + def setuid(self, uid=None): + self.uid = uid + + def getname(self): + return self.name + + # name setter + + def setname(self, name=None): + self.name = name + + def getphone(self): + return self.phone + + def setphone(self, phone=None): + self.phone = phone diff --git a/FreeTAKServer/model/FTSModel/Dest.py b/FreeTAKServer/model/FTSModel/Dest.py new file mode 100644 index 00000000..74137bc3 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Dest.py @@ -0,0 +1,24 @@ +from FreeTAKServer.model.FTSModelVariables.DestVariables import DestVariables as vars + +class Dest: + def __init__(self, CALLSIGN = vars.other().CALLSIGN): + self.callsign = None + self.setcallsign(CALLSIGN) + + @staticmethod + def other(CALLSIGN = vars.geochat().CALLSIGN): + dest = Dest() + + return dest + + @staticmethod + def geochat(CALLSIGN = vars.geochat().CALLSIGN): + dest = Dest() + dest.setcallsign(CALLSIGN) + return dest + + def getcallsign(self): + return self.callsign + + def setcallsign(self, callsign=0): + self.callsign = callsign diff --git a/FreeTAKServer/model/FTSModel/Detail.py b/FreeTAKServer/model/FTSModel/Detail.py new file mode 100644 index 00000000..1296cf43 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Detail.py @@ -0,0 +1,227 @@ +####################################################### +# +# detail.py +# Python implementation of the Class detail +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:07 AM +# Original author: Corvo +# +####################################################### +from FreeTAKServer.model.FTSModel.Takv import Takv +from FreeTAKServer.model.FTSModel.Uid import Uid +from FreeTAKServer.model.FTSModel.Precisionlocation import Precisionlocation +from FreeTAKServer.model.FTSModel._Group import _Group +from FreeTAKServer.model.FTSModel.Status import Status +from FreeTAKServer.model.FTSModel.Track import Track +from FreeTAKServer.model.FTSModel.Marti import Marti +from FreeTAKServer.model.FTSModel.Link import Link +from .Contact import Contact +from .Emergency import Emergency +from FreeTAKServer.model.FTSModel.Chat import Chat +from FreeTAKServer.model.FTSModel.Remarks import Remarks +from FreeTAKServer.model.FTSModel.Serverdestination import _Serverdestination as Serverdestination +from .Color import Color +from FreeTAKServer.model.FTSModel.Usericon import Usericon +from .Archive import Archive +from FreeTAKServer.model.FTSModel.Summary import Summary + +class Detail: + """An optional element used to hold CoT sub-schema. empty element + """ + def __init__(self): + pass + + @staticmethod + def Connection(): + detail = Detail() + detail.takv = Takv.connection() + detail.contact = Contact.connection() + detail.uid = Uid.connection() + detail.precisionlocation = Precisionlocation.connection() + detail._group = _Group.connection() + detail.status = Status.connection() + detail.track = Track.connection() + return detail + + @staticmethod + def GeoChat(): + detail = Detail() + detail._chat = Chat.geochat() + detail.link = Link.geochat() + detail.remarks = Remarks.geochat() + detail._serverdestination = Serverdestination.geochat() + detail.marti = Marti.drop_point() + return detail + + @staticmethod + def Ping(): + detail = Detail() + detail.setuid(None) + return detail + + @staticmethod + def FederatedCoT(): + detail = Detail() + detail.setuid(None) + return detail + + @staticmethod + def Other(): + detail = Detail() + detail.marti = Marti.other() + return detail + + @staticmethod + def emergencyOn(): + detail = Detail() + detail.link = Link.emergency_on() + detail.contact = Contact.emergency_on() + detail.emergency = Emergency.emergency_on() + return detail + + @staticmethod + def emergencyOff(): + detail = Detail() + detail.emergency = Emergency.emergency_off() + return detail + + @staticmethod + def dropPoint(): + detail = Detail() + detail.archive = Archive.drop_point() + detail.status = Status.drop_point() + detail.usericon = Usericon.drop_point() + detail.link = Link.drop_point() + detail.color = Color.drop_point() + detail.precisionlocation = Precisionlocation.drop_point() + detail.contact = Contact.drop_point() + detail.remarks = Remarks.drop_point() + detail.marti = Marti.drop_point() + detail.summary = Summary.drop_point() + return detail + + @staticmethod + def disconnect(): + detail = Detail() + detail.link = Link.disconnect() + return detail + + @staticmethod + def UserUpdate(): + detail = Detail() + detail._group = _Group.UserUpdate() + detail.status = Status.UserUpdate() + detail.takv = Takv.UserUpdate() + detail.track = Track.UserUpdate() + detail.contact = Contact.UserUpdate() + detail.uid = Uid.UserUpdate() + detail.precisionlocation = Precisionlocation.UserUpdate() + return detail + + def setarchive(self, archive): + self.archive = archive + + def getarchive(self): + return self.archive + + def setsummary(self, summary): + self.summary = summary + + def getsummary(self): + return self.summary + + def setremarks(self, remarks): + self.remarks = remarks + + def getremarks(self): + return self.remarks + + def setlink(self, link): + self.link = link + + def getlink(self): + return self.link + + def setstatus(self, status): + self.status = status + + def getstatus(self): + return self.status + + def setusericon(self, usericon): + self.usericon = usericon + + def getusericon(self): + return self.usericon + + def setcolor(self, color): + self.color = color + + def getcolor(self): + return self.color + + def setcontact(self, contact): + self.contact = contact + + def getcontact(self): + return self.contact + + def sethierarchy(self, hierarchy): + self.hierarchy = hierarchy + + def gethierarchy(self): + return self.hierarchy + + def setuid(self, uid): + self.uid = uid + + def getuid(self): + return self.uid + + def settakv(self, takv): + self.takv = takv + + def gettakv(self): + return self.takv + + def set__group(self, group): + self._group = group + + def get__group(self): + return self._group + + def setprecisionlocation(self, Precisionlocation): + self.precisionlocation = Precisionlocation + + def getprecisionlocation(self): + return self.precisionlocation + + def settrack(self, track): + self.track = track + + def gettrack(self): + return self.track + + def setmarti(self, marti): + self.marti = marti + + def getmarti(self): + return self.marti + + def setemergency(self, emergency): + self.emergency = emergency + + def getemergency(self): + return self.emergency + + def set__chat(self, chat): + self._chat = chat + + def get__chat(self): + return self._chat + + def set__serverdestination(self, serverdestination): + self._serverdestination = serverdestination + + def get__serverdestination(self): + return self._serverdestination \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/DimensionTypes.py b/FreeTAKServer/model/FTSModel/DimensionTypes.py new file mode 100644 index 00000000..5aa78981 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/DimensionTypes.py @@ -0,0 +1,95 @@ +####################################################### +# +# DimensionTypes.py +# Python implementation of the Class DimensionTypes +# Generated by Enterprise Architect +# Created on: 11Feb2020 11:08:09 AM +# Original author: Corvo +# +####################################################### + + +class DimensionTypes: +# default constructor def __init__(self): + + space = "p" + # space getter + def getspace(self): + return self.space + + # space setter + def setspace(self,space=0): + self.space=space + + air = "A" + # air getter + def getair(self): + return self.air + + # air setter + def setair(self,air=0): + self.air=air + + landunit = "G" + # landunit getter + def getlandunit(self): + return self.landunit + + # landunit setter + def setlandunit(self,landunit=0): + self.landunit=landunit + + landequipment = "G" + # landequipment getter + def getlandequipment(self): + return self.landequipment + + # landequipment setter + def setlandequipment(self,landequipment=0): + self.landequipment=landequipment + + landinstallation = "G" + # landinstallation getter + def getlandinstallation(self): + return self.landinstallation + + # landinstallation setter + def setlandinstallation(self,landinstallation=0): + self.landinstallation=landinstallation + + seasurface = "S" + # seasurface getter + def getseasurface(self): + return self.seasurface + + # seasurface setter + def setseasurface(self,seasurface=0): + self.seasurface=seasurface + + seasubsurface = "U" + # seasubsurface getter + def getseasubsurface(self): + return self.seasubsurface + + # seasubsurface setter + def setseasubsurface(self,seasubsurface=0): + self.seasubsurface=seasubsurface + + subsurface = "U" + # subsurface getter + def getsubsurface(self): + return self.subsurface + + # subsurface setter + def setsubsurface(self,subsurface=0): + self.subsurface=subsurface + + other = "X" + # other getter + def getother(self): + return self.other + + # other setter + def setother(self,other=0): + self.other=other + \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/Emergency.py b/FreeTAKServer/model/FTSModel/Emergency.py new file mode 100644 index 00000000..295d179f --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Emergency.py @@ -0,0 +1,61 @@ +####################################################### +# +# Emergency.py +# Python implementation of the Class Emergency +# Generated by Enterprise Architect +# Created on: 13-Apr-2020 4:40:22 PM +# Original author: Corvo +# +####################################################### +from FreeTAKServer.model.FTSModelVariables.EmergencyVariables import EmergencyVariables as vars + +class Emergency: + """An Emergency beacon the is continually send to all the connected clients until + deactivated from the original creator + """ + def __init__(self): + self.type = None + self.alert = None + # if true the Emergency beacon is canceled + self.cancel = None + self.INTAG = None + + @staticmethod + def emergency_on(INTAG = vars.emergency_on().INTAG, TYPE = vars.emergency_on().TYPE, ALERT = vars.emergency_on().ALERT, CANCEL = vars.emergency_on().CANCEL): + emergency = Emergency() + emergency.settype(TYPE) + emergency.setAlert(ALERT) + emergency.setcancel(CANCEL) + emergency.setINTAG(INTAG) + return emergency + + @staticmethod + def emergency_off(CANCEL = vars.emergency_off().CANCEL, INTAG = vars.emergency_off().INTAG): + emergency = Emergency() + emergency.setcancel(CANCEL) + emergency.setINTAG(INTAG) + return emergency + + def settype(self, type=None): + self.type = type + + def gettype(self): + return self.type + + def setAlert(self, alert=None): + self.alert = alert + + def getAlert(self): + return self.alert + + def setcancel(self, cancel=None): + self.cancel = cancel + + def getcancel(self): + return self.cancel + + def setINTAG(self, INTAG=None): + self.INTAG = INTAG + + def getINTAG(self): + return self.INTAG diff --git a/FreeTAKServer/model/FTSModel/EntityTypes.py b/FreeTAKServer/model/FTSModel/EntityTypes.py new file mode 100644 index 00000000..884612de --- /dev/null +++ b/FreeTAKServer/model/FTSModel/EntityTypes.py @@ -0,0 +1,36 @@ +####################################################### +# +# EntityTypes.py +# Python implementation of the Class EntityTypes +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:09 AM +# Original author: Corvo +# +####################################################### + + +class EntityTypes: +# default constructor def __init__(self): + + military = "" + + + + civilian = "" + # civilian getter + def getcivilian(self): + return self.civilian + + # civilian setter + def setcivilian(self, civilian=0): + self.civilian=civilian + + # military getter + def getmilitary(self): + return self.military + + # military setter + def setmilitary(self, military=0): + self.military=military + + \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/Event.py b/FreeTAKServer/model/FTSModel/Event.py new file mode 100644 index 00000000..fcd2db86 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Event.py @@ -0,0 +1,376 @@ +import datetime as dt +from FreeTAKServer.model.FTSModel.Detail import Detail +from .Point import Point +from FreeTAKServer.model.FTSModelVariables.EventVariables import EventVariables as vars +import uuid + +class Event: + # TODO: fix emergency methods + # Event.py + # Python implementation of the Class Event + # represents a TAK event: this class is instantiated with a standard set of + # values. + # Generated by Enterprise Architect + # Created on: 11-Feb-2020 11:08:07 AM + # Original author: Corvo + # + + # event as an XML + # + + #default constructor + + def __init__(self): + + + self.version = None + self.uid = None + self.type = None + self.how = None + + self.detail = None + self.point = None + self.start = None + case = { + + 'default': self.defaultFunc, + + 'timeout': self.timeoutFunc + + } + + + # flag to determin e if this event is a geo chcat if so, will be added as a + # prefix to the uid + + # starting time when an event should be considered valid + start = "%Y-%m-%dT%H:%M:%SZ" + # basic event + # Gives a hint about how the coordinates were generated + + + # Schema version of this event instance (e.g. 2.0) + + # time stamp: when the event was generated + time = "%Y-%m-%dT%H:%M:%SZ" + + # Hierarchically organized hint about event type (defaultis is 'a-f-G-I' + # for infrastructure) + + # ending time when an event should no longer be considered valid + stale = "%Y-%m-%dT%H:%M:%SZ" + + # Globally unique name for this information on this event can have + # additional information attached. + # e.g. -ping means that this request is a ping + + # flag to determine if this event is a Ping, in this case append to the UID + + @staticmethod + def Connection(version=vars.connection().VERSIONNUM, uid=vars.connection().UID, type=vars.connection().TYPE, + how=vars.connection().HOW, time=vars.connection().TIME, start=vars.connection().START, + stale=vars.connection().STALE): + event = Event() + event.setdetail(Detail.Connection()) + event.setpoint(Point()) + event.setversion(version) + event.setuid(uid) + event.settype(type) + event.sethow(how) + event.settime(time) + event.setstart(start) + event.setstale(stale) + return event + + @staticmethod + def GeoChat(version=vars.geochat().VERSIONNUM, uid=vars.geochat().UID, type=vars.geochat().TYPE, + how=vars.geochat().HOW, time=vars.geochat().TIME, start=vars.geochat().START, + stale=vars.geochat().STALE): + event = Event() + event.setdetail(Detail.GeoChat()) + event.setpoint(Point()) + event.setversion(version) + event.setuid(uid) + event.settype(type) + event.sethow(how) + event.settime(time) + event.setstart(start) + event.setstale(stale) + return event + + @staticmethod + def Ping(version=vars.ping().VERSIONNUM, uid=vars.ping().UID, type=vars.ping().TYPE, + how=vars.ping().HOW, time=vars.ping().TIME, start=vars.ping().START, + stale=vars.ping().STALE): + event = Event() + event.setdetail(Detail.Ping()) + event.setpoint(Point()) + event.setversion(version) + event.setuid(uid) + event.settype(type) + event.sethow(how) + event.settime(time) + event.setstart(start) + event.setstale(stale) + return event + + @staticmethod + def Other(version=vars.other().VERSIONNUM, uid=vars.other().UID, type=vars.other().TYPE, + how=vars.other().HOW, time=vars.other().TIME, start=vars.other().START, + stale=vars.other().STALE): + event = Event() + event.setdetail(Detail.Other()) + event.setpoint(Point()) + event.setversion(version) + event.setuid(uid) + event.settype(type) + event.sethow(how) + event.settime(time) + event.setstart(start) + event.setstale(stale) + return event + + @staticmethod + # this is the only constructor which doesn't instantiate detail as detail is a required protobuf + # attribute and will therefore be in the message regardless + def FederatedCoT(version=vars.FederatedCoT().VERSIONNUM, uid=vars.FederatedCoT().UID, type=vars.FederatedCoT().TYPE, + how=vars.FederatedCoT().HOW, time=vars.FederatedCoT().TIME, start=vars.FederatedCoT().START, + stale=vars.FederatedCoT().STALE): + event = Event() + event.setpoint(Point()) + event.setversion(version) + event.setuid(uid) + event.settype(type) + event.sethow(how) + event.settime(time) + event.setstart(start) + event.setstale(stale) + return event + + @staticmethod + def emergecyOn(version=vars.emergency_on().VERSIONNUM, uid=vars.emergency_on().UID, type=vars.emergency_on().TYPE, + how=vars.emergency_on().HOW, time=vars.emergency_on().TIME, start=vars.emergency_on().START, + stale=vars.emergency_on().STALE): + event = Event() + event.setdetail(Detail.emergencyOn()) + event.setpoint(Point()) + event.setversion(version) + event.setuid(uid) + event.settype(type) + event.sethow(how) + event.settime(time) + event.setstart(start) + event.setstale(stale) + return event + + @staticmethod + def emergecyOff(version=vars.emergency_off().VERSIONNUM, uid=vars.emergency_off().UID, type=vars.emergency_off().TYPE, + how=vars.emergency_off().HOW, time=vars.emergency_off().TIME, start=vars.emergency_off().START, + stale=vars.emergency_off().STALE): + event = Event() + event.setdetail(Detail.emergencyOff()) + event.setpoint(Point()) + event.setversion(version) + event.setuid(uid) + event.settype(type) + event.sethow(how) + event.settime(time) + event.setstart(start) + event.setstale(stale) + return event + + @staticmethod + def dropPoint(version=vars.drop_point().VERSIONNUM, uid=vars.drop_point().UID, type=vars.drop_point().TYPE, + how=vars.drop_point().HOW, time=vars.drop_point().TIME, start=vars.drop_point().START, + stale=vars.drop_point().STALE): + event = Event() + event.setdetail(Detail.dropPoint()) + event.setpoint(Point()) + event.setversion(version) + event.setuid(uid) + event.settype(type) + event.sethow(how) + event.settime(time) + event.setstart(start) + event.setstale(stale) + return event + + @staticmethod + def disconnect(UID=vars.disconnect().uid, VERSION=vars.disconnect().version, TYPE=vars.disconnect().type, + TIME=vars.disconnect().time, START=vars.disconnect().start, STALE=vars.disconnect().stale, + HOW=vars.disconnect().how): + event = Event() + event.setuid(UID) + event.setversion(VERSION) + event.settype(TYPE) + event.settime(TIME) + event.setstart(START) + event.setstale(STALE) + event.sethow(HOW) + event.point = Point() + event.detail = Detail.disconnect() + return event + + @staticmethod + def takPong(VERSION=vars.takPong().version, UID=vars.takPong().uid, TYPE=vars.takPong().type, + HOW=vars.takPong().how, TIME=vars.takPong().time, START=vars.takPong().start, + STALE=vars.takPong().stale): + event = Event() + event.setversion(VERSION) + event.setuid(UID) + event.settype(TYPE) + event.sethow(HOW) + event.settime(TIME) + event.setstart(START) + event.setstale(STALE) + event.point = Point() + return event + + @staticmethod + def UserUpdate(VERSION=vars.UserUpdate().version, UID=vars.UserUpdate().uid, TYPE=vars.UserUpdate().type, + HOW=vars.UserUpdate().how, TIME=vars.UserUpdate().time, START=vars.UserUpdate().start, + STALE=vars.UserUpdate().stale): + event = Event() + event.setversion(VERSION) + event.setuid(UID) + event.settype(TYPE) + event.sethow(HOW) + event.settime(TIME) + event.setstart(START) + event.setstale(STALE) + event.point = Point() + event.detail = Detail.UserUpdate() + return event + + def defaultFunc(self, DATETIME_FMT, version, uid, type, how, isGeochat, isPing): + self.how = how + + timer = dt.datetime + now = timer.utcnow() + zulu = now.strftime(DATETIME_FMT) + stale_part = dt.datetime.strptime(zulu, DATETIME_FMT) + dt.timedelta(minutes = 1) + stale_part = stale_part.strftime(DATETIME_FMT) + self.setstale(str(stale_part)) + self.setstart(zulu) + self.settime(zulu) + self.type = type + self.setuid(isGeochat=isGeochat, isPing=isPing) + self.version = version + + def timeoutFunc(self, DATETIME_FMT, version, uid, type, how, isGeochat, isPing): + self.how = how + + timer = dt.datetime + now = timer.utcnow() + zulu = now.strftime(DATETIME_FMT) + stale_part = dt.datetime.strptime(zulu, DATETIME_FMT) + dt.timedelta(minutes = 1) + stale_part = stale_part.strftime(DATETIME_FMT) + self.setstale(str(stale_part)) + self.setstart(zulu) + self.settime(zulu) + self.type = type + self.setuid(isGeochat=isGeochat, isPing=isPing) + self.version = version + #start getter + + def getstart(self): + return self.start + + # start setter + def setstart(self, start=0): + DATETIME_FMT = "%Y-%m-%dT%H:%M:%S.%fZ" + if start == None: + timer = dt.datetime + now = timer.utcnow() + zulu = now.strftime(DATETIME_FMT) + self.start = zulu + else: + self.start = start + + + # how getter + def gethow(self): + return self.how + + + # how setter + def sethow(self, how=0): + self.how = how + + # uid getter + def getuid(self): + return self.uid + + # uid setter + def setuid(self, uid): + if uid == None: + self.uid = str(uuid.uuid1()) + + else: + self.uid = uid + + # version getter + def getversion(self): + return self.version + + # version setter + def setversion(self, version): + self.version = version + + # time getter + def gettime(self): + return self.time + + # time setter + def settime(self, time=0): + DATETIME_FMT = "%Y-%m-%dT%H:%M:%S.%fZ" + if time == None: + timer = dt.datetime + now = timer.utcnow() + zulu = now.strftime(DATETIME_FMT) + self.time = zulu + else: + self.time = time + + # stale getter + def getstale(self): + return self.stale + + # stale setter + def setstale(self, stale=0): + DATETIME_FMT = "%Y-%m-%dT%H:%M:%S.%fZ" + if stale == None: + timer = dt.datetime + now = timer.utcnow() + zulu = now.strftime(DATETIME_FMT) + add = dt.timedelta(minutes=1) + stale_part = dt.datetime.strptime(zulu, DATETIME_FMT) + add + self.stale = stale_part.strftime(DATETIME_FMT) + else: + self.stale = stale + + # type getter + def gettype(self): + return self.type + + # type setter + def settype(self, type=0): + self.type = type + + def getpoint(self): + return self.point + + # type setter + + def setpoint(self, Point=None): + self.point = Point + + def getdetail(self): + return self.detail + + # type setter + + def setdetail(self, detail=None): + self.detail = detail +if __name__ == "__main__": + Event() \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/Group.py b/FreeTAKServer/model/FTSModel/Group.py new file mode 100644 index 00000000..d75ad8a4 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Group.py @@ -0,0 +1,28 @@ +from FreeTAKServer.model.FTSModel.Contact import Contact + +class Group: + def __init__(self, xml): + self.uid = None + self.name = None + self.setuid(xml.get('uid')) + self.setname(xml.get('name')) + try: + self.contact = Contact() + except: + pass + try: + self.Group = Group(xml.find('group')) + except: + pass + + def setuid(self, uid=None): + self.uid = uid + + def getuid(self): + return self.uid + + def setname(self, name=None): + self.name = name + + def getname(self): + return self.name \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/Hierarchy.py b/FreeTAKServer/model/FTSModel/Hierarchy.py new file mode 100644 index 00000000..576f5456 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Hierarchy.py @@ -0,0 +1,8 @@ +from .Group import Group + +class Hierarchy: + def __init__(self, xml): + try: + self.Group = Group(xml.find('group')) + except: + pass \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/IdentityTypes.py b/FreeTAKServer/model/FTSModel/IdentityTypes.py new file mode 100644 index 00000000..6ea1be27 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/IdentityTypes.py @@ -0,0 +1,98 @@ +####################################################### +# +# IdentityTypes.py +# Python implementation of the Class IdentityTypes +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:08 AM +# Original author: Corvo +# +####################################################### + + +class IdentityTypes: + # default constructor def __init__(self,): + + # pending + pending = "p" + # pending getter + def getpending(self,): + return self.pending + + # pending setter + def setpending(self,pending=0): + self.pending=pending + + # unknown + unknown = "u" + # unknown getter + def getunknown(self,): + return self.unknown + + # unknown setter + def setunknown(self,unknown=0): + self.unknown=unknown + + # friend + friend = "f" + # friend getter + def getfriend(self,): + return self.friend + + # friend setter + def setfriend(self,friend=0): + self.friend=friend + + neutral = "n" + # neutral getter + def getneutral(self,): + return self.neutral + + # neutral setter + def setneutral(self,neutral=0): + self.neutral=neutral + + hostile = "h" + # hostile getter + def gethostile(self,): + return self.hostile + + # hostile setter + def sethostile(self,hostile=0): + self.hostile=hostile + + assumedfriend = "a" + # assumed-friend getter + def getassumedfriend(self,): + return self.assumedfriend + + # assumed-friend setter + def setassumedfriend(self, assumedfriend=0): + self.assumedfriend=assumedfriend + + suspect = "s" + # suspect getter + def getsuspect(self,): + return self.suspect + + # suspect setter + def setsuspect(self,suspect=0): + self.suspect=suspect + + joker = "j" + # joker getter + def getjoker(self,): + return self.joker + + # joker setter + def setjoker(self,joker=0): + self.joker=joker + + faker = "f" + # faker getter + def getfaker(self,): + return self.faker + + # faker setter + def setfaker(self,faker=0): + self.faker=faker + \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/Link.py b/FreeTAKServer/model/FTSModel/Link.py new file mode 100644 index 00000000..141f0d93 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Link.py @@ -0,0 +1,111 @@ +####################################################### +# +# Link.py +# Python implementation of the Class Link +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:08 AM +# Original author: Corvo +# +####################################################### +import datetime as dt +from FreeTAKServer.model.FTSModelVariables.LinkVariables import LinkVariables as vars + +class Link: + def __init__(self): + self.uid = None + self.relation = None + self.production_time = None + self.type = None + self.parent_callsign = None + + @staticmethod + def drop_point(UID = vars.drop_point().UID, RELATION = vars.drop_point().RELATION, + PRODUCTIONTIME = vars.drop_point().PRODUCTIONTIME, + TYPE = vars.drop_point().TYPE, PARENTCALLSIGN = vars.drop_point().PARENTCALLSIGN): + link = Link() + link.setuid(UID) + link.setrelation(RELATION) + link.setproduction_time(PRODUCTIONTIME) + link.settype(TYPE) + link.setparent_callsign(PARENTCALLSIGN) + return link + + @staticmethod + def geochat(UID=vars.geochat().UID, RELATION=vars.geochat().RELATION, + PRODUCTIONTIME=vars.geochat().PRODUCTIONTIME, TYPE=vars.geochat().TYPE, + PARENTCALLSIGN=vars.geochat().PARENTCALLSIGN): + link = Link() + link.setuid(UID) + link.setrelation(RELATION) + link.settype(TYPE) + link.setparent_callsign(PARENTCALLSIGN) + return link + + @staticmethod + def emergency_on(UID=vars.emergency_on().UID, RELATION=vars.emergency_on().RELATION, + PRODUCTIONTIME=vars.emergency_on().PRODUCTIONTIME, TYPE=vars.emergency_on().TYPE, + PARENTCALLSIGN=vars.emergency_on().PARENTCALLSIGN): + link = Link() + link.setuid(UID) + link.setrelation(RELATION) + link.setproduction_time(PRODUCTIONTIME) + link.settype(TYPE) + link.setparent_callsign(PARENTCALLSIGN) + return link + + @staticmethod + def disconnect(UID=vars.disconnect().uid, TYPE=vars.disconnect().type, RELATION=vars.disconnect().relation): + link = Link() + link.setuid(UID) + link.settype(TYPE) + link.setrelation(RELATION) + return link + + # uid getter + def getuid(self): + return self.uid + + # uid setter + def setuid(self, uid=0): + self.uid=uid + + # production_time getter + def getproduction_time(self): + return self.production_time + + # production_time setter + def setproduction_time(self, production_time=0): + DATETIME_FMT = "%Y-%m-%dT%H:%M:%SZ" + if production_time == None: + timer = dt.datetime + now = timer.utcnow() + zulu = now.strftime(DATETIME_FMT) + add = dt.timedelta(minutes=1) + production_time_part = dt.datetime.strptime(zulu, DATETIME_FMT) + add + self.production_time = production_time_part.strftime(DATETIME_FMT) + else: + self.production_time = production_time + + # relation getter + def getrelation(self): + return self.relation + + # relation setter + def setrelation(self, relation=0): + self.relation=relation + + # type getter + def gettype(self): + return self.type + + # type setter + def settype(self, type=0): + self.type=type + + # parent_callsign getter + def getparent_callsign(self): + return self.parent_callsign + + # parent_callsign setter + def setparent_callsign(self, parent_callsign=0): + self.parent_callsign=parent_callsign diff --git a/FreeTAKServer/model/FTSModel/Marti.py b/FreeTAKServer/model/FTSModel/Marti.py new file mode 100644 index 00000000..b3515466 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Marti.py @@ -0,0 +1,62 @@ +from FreeTAKServer.model.FTSModel.Dest import Dest as DestObject + +#TODO: modify to call dest with static method +set_count = 0 +index_count = -1 + +class Marti: + + def __init__(self): + self.dest = [DestObject()] + + @staticmethod + def other(): + global set_count, index_count + set_count = 0 + index_count = 0 + marti = Marti() + return marti + + @staticmethod + def geochat(): + global set_count, index_count + set_count = 0 + index_count = 0 + marti = Marti() + return marti + + @staticmethod + def drop_point(): + global set_count, index_count + set_count = 0 + index_count = 0 + marti = Marti() + return marti + + def getdest(self): + global index_count + index_counta = index_count + dest = self.dest[index_count] + index_count += 1 + return dest + + def setdest(self, Dest = None): + global set_count + self.dest[set_count] = Dest + set_count += 1 + self.dest.append(DestObject()) + +if __name__ == "__main__": + from FreeTAKServer.controllers.XMLCoTController import XMLCoTController + from lxml import etree + a = Marti.other() + b = etree.fromstring(b'') + x = XMLCoTController().serialize_CoT_to_model(a, b) + y = x.getdest().callsign + print(a.__dict__) + M = DestObject() + M.setcallsign('13243432w') + a.setdest(M) + for x in a.dest: + f = a.getdest() + print('done') \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/Mission.py b/FreeTAKServer/model/FTSModel/Mission.py new file mode 100644 index 00000000..c01b24df --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Mission.py @@ -0,0 +1,43 @@ +####################################################### +# +# Mission.py +# Python implementation of the Class Mission +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:08 AM +# Original author: Corvo +# +####################################################### + + +class Mission: + """Reppresent a TAK Mission + """ +# default constructor def __init__(self): + + name = "" + # name getter + def getname(self): + return self.name + + # name setter + def setname(self,name=0): + self.name=name + + __server = "" + # server getter + def getserver(self): + return self.server + + # server setter + def setserver(self,server=0): + self.server=server + + __description = "" + # description getter + def getdescription(self): + return self.description + + # description setter + def setdescription(self,description=0): + self.description=description + \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/Point.py b/FreeTAKServer/model/FTSModel/Point.py new file mode 100644 index 00000000..88e89603 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Point.py @@ -0,0 +1,58 @@ +####################################################### +# +# point.py +# Python implementation of the CoT point +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:07 AM +# Original author: Corvo +# +####################################################### +# Latitude referred to the WGS 84 ellipsoid in degrees +from FreeTAKServer.model.FTSModelVariables.PointVariables import PointVariables as vars + +class Point: + + def __init__(self, le=vars().LE, ce=vars().CE, hae=vars().HAE, lon=vars().LON, lat=vars().LAT): + self.le = le + self.ce = ce + self.hae = hae + self.lon = lon + self.lat = lat + + # ce getter + def getce(self): + return self.ce + + # ce setter + def setce(self, ce): + self.ce=ce + + # le getter + def getle(self): + return self.le + + # le setter + def setle(self,le): + self.le=le + + # lat getter + def getlat(self): + return self.lat + + # lat setter + def setlat(self, lat): + self.lat=lat + + # lon getter + def getlon(self): + return self.lon + + # lon setter + def setlon(self,lon): + self.lon=lon + + def gethae(self): + return self.hae + + def sethae(self,hae): + self.hae = hae diff --git a/FreeTAKServer/model/FTSModel/Precisionlocation.py b/FreeTAKServer/model/FTSModel/Precisionlocation.py new file mode 100644 index 00000000..3b8707df --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Precisionlocation.py @@ -0,0 +1,59 @@ +####################################################### +# +# Precisionlocation.py +# Python implementation of the Class Precisionlocation +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:10 AM +# Original author: Corvo +# +####################################################### +from FreeTAKServer.model.FTSModelVariables.PrecisionlocationVariables import PrecisionlocationVariables as vars + +class Precisionlocation: + """some type of location? + """ + +# TDB can be DTED0 or ??? + + + # default constructor + def __init__(self): + self.altsrc = None + self.geopointsrc = None + + @staticmethod + def drop_point(ALTSRC = vars.drop_point().ALTSRC): + precisionlocation = Precisionlocation() + precisionlocation.setaltsrc(altsrc=ALTSRC) + return precisionlocation + + @staticmethod + def connection(ALTSRC = vars.connection().ALTSRC, GEOPOINTSRC = vars.connection().GEOPOINTSRC): + precisionlocation = Precisionlocation() + precisionlocation.setaltsrc(altsrc=ALTSRC) + precisionlocation.setgeopointsrc(geopointsrc=GEOPOINTSRC) + return precisionlocation + + @staticmethod + def UserUpdate(ALTSRC=vars.UserUpdate().altsrc, GEOPOINTSRC=vars.UserUpdate().geopointsrc): + precisionlocation = Precisionlocation() + precisionlocation.setaltsrc(ALTSRC) + precisionlocation.setgeopointsrc(GEOPOINTSRC) + return precisionlocation + + # geopointsrc getter + def getgeopointsrc(self): + return self.geopointsrc + + # geopointsrc setter + def setgeopointsrc(self, geopointsrc=0): + self.geopointsrc=geopointsrc + + # altsrc getter + def getaltsrc(self): + return self.altsrc + + # altsrc setter + def setaltsrc(self, altsrc=0): + self.altsrc=altsrc + \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/Remarks.py b/FreeTAKServer/model/FTSModel/Remarks.py new file mode 100644 index 00000000..137b5ab7 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Remarks.py @@ -0,0 +1,85 @@ +####################################################### +# +# remarks.py +# Python implementation of the Class remarks +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:08 AM +# Original author: Corvo +# +####################################################### +from FreeTAKServer.model.FTSModelVariables.RemarksVariables import RemarksVariables as vars +import datetime as dt + +class Remarks: + """Provides a place to annotate CoT with free text information. e.g. comments + from other users about the current COT. Used also fro the geoChat. + the xml body of this class is used to transport the chat message + """ + def __init__(self): + self.time = None + self.source = None + self.sourceID = None + self.to = None + + @staticmethod + def drop_point(TIME = vars.drop_point().TIME, SOURCE = vars.drop_point().SOURCE, SOURCEID = vars.geochat().SOURCEID, INTAG = vars.geochat().INTAG): + remarks = Remarks() + remarks.settime(time=TIME) + remarks.setsource(source=SOURCE) + remarks.setsourceID(SOURCEID) + remarks.setINTAG(INTAG) + return remarks + + @staticmethod + def geochat(TIME = vars.geochat().TIME, SOURCE = vars.geochat().SOURCE, SOURCEID = vars.geochat().SOURCEID, INTAG = vars.geochat().INTAG, TO = vars.geochat().TO): + remarks = Remarks() + remarks.settime(time=TIME) + remarks.setsource(source=SOURCE) + remarks.setsourceID(SOURCEID) + remarks.setINTAG(INTAG) + remarks.setto(TO) + return remarks + + # time getter + def gettime(self): + return self.time + + # time setter + def settime(self, time=0): + DATETIME_FMT = "%Y-%m-%dT%H:%M:%SZ" + if time == None: + timer = dt.datetime + now = timer.utcnow() + zulu = now.strftime(DATETIME_FMT) + self.time = zulu + else: + self.time = time + + # to getter + def getto(self): + return self.to + + # to setter + def setto(self, to=0): + self.to=to + + # source getter + def getsource(self): + return self.source + + # source setter + def setsource(self, source=0): + self.source=source + + def getsourceID(self): + return self.sourceID + + # source setter + def setsourceID(self, sourceID=0): + self.sourceID = sourceID + + def setINTAG(self, INTAG): + self.INTAG = INTAG + + def getINTAG(self, INTAG): + return self.INTAG \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/Serverdestination.py b/FreeTAKServer/model/FTSModel/Serverdestination.py new file mode 100644 index 00000000..d5560cca --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Serverdestination.py @@ -0,0 +1,30 @@ +####################################################### +# +# __serverdestination.py +# Python implementation of the Class __serverdestination +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:10 AM +# Original author: Corvo +# +####################################################### +from FreeTAKServer.model.FTSModelVariables.ServerdestinationVariables import ServerdestionationVariables as vars + +class _Serverdestination: + def __init__(self): + # string composed by IP:port: protocol:machineID. e.g. 192.168.0.103:4242:tcp: + # ANDROID-R52JB0CDC4E + self.destinations = None + # destinations getter + + @staticmethod + def geochat(DESTINATIONS = vars.geochat().DESTINATIONS): + serverdestinations = _Serverdestination() + serverdestinations.setdestinations(DESTINATIONS) + return serverdestinations + + def getdestinations(self): + return self.destinations + + # destinations setter + def setdestinations(self, destinations=None): + self.destinations = destinations \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/Status.py b/FreeTAKServer/model/FTSModel/Status.py new file mode 100644 index 00000000..c7516349 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Status.py @@ -0,0 +1,58 @@ +####################################################### +# +# Status.py +# Python implementation of the Class Status +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:07 AM +# Original author: Corvo +# +####################################################### +from FreeTAKServer.model.FTSModelVariables.statusVariables import statusVariables as vars + +class Status: + def __init__(self): + self.battery = vars().BATTERY + self.readiness = vars().READINESS + # % of the battery on the phone + + @staticmethod + def drop_point(battery=vars.drop_point().BATTERY, readiness=vars.drop_point().READINESS): + status = Status() + status.setbattery(battery=battery) + status.setreadiness(readiness=readiness) + return status + + @staticmethod + def connection(battery=vars.connection().BATTERY, readiness=vars.connection().READINESS): + status = Status() + status.setbattery(battery=battery) + status.setreadiness(readiness=readiness) + return status + + @staticmethod + def UserUpdate(BATTERY=vars.UserUpdate().battery): + status = Status() + status.setbattery(BATTERY) + return status + + # battery getter + def getbattery(self): + return self.battery + + # battery setter + def setbattery(self, battery=0): + self.battery = battery + + # probably boolean to determine if ready or not + + # readiness getter + def getreadiness(self): + return self.readiness + + # readiness setter + def setreadiness(self, readiness=0): + self.readiness = readiness + + +if __name__ == "__main__": + Status() \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/Summary.py b/FreeTAKServer/model/FTSModel/Summary.py new file mode 100644 index 00000000..aea43dd3 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Summary.py @@ -0,0 +1,17 @@ +from FreeTAKServer.model.FTSModelVariables.SummaryVariables import SummaryVariables as vars + +class Summary: + def __init__(self): + self.INTAG = vars().INTAG + + @staticmethod + def drop_point(INTAG = vars.drop_point().INTAG): + summary = Summary() + summary.INTAG = INTAG + return summary + + def setINTAG(self, INTAG = None): + self.INTAG = INTAG + + def getINTAG(self): + return self.INTAG \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModel/Takv.py b/FreeTAKServer/model/FTSModel/Takv.py new file mode 100644 index 00000000..c7733622 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Takv.py @@ -0,0 +1,77 @@ +####################################################### +# +# Takv.py +# Python implementation of the Class Takv +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:09 AM +# Original author: Corvo +# +####################################################### +from FreeTAKServer.model.FTSModelVariables.TakvVariables import TakvVariables as vars + +class Takv: + +# default constructor + def __init__(self): + # the version of TAK running on the device + self.version = None + # the variant of TAK + self.platform = None + # type of physical device + self.device = None + # the operating system running TAK + self.os = None + + @staticmethod + def connection(VERSION = vars.connection().VERSION, PLATFORM = vars.connection().PLATFORM, + DEVICE = vars.connection().DEVICE, OS = vars.connection().OS): + + takv = Takv() + takv.setversion(VERSION) + takv.setplatform(PLATFORM) + takv.setos(OS) + takv.setdevice(DEVICE) + return takv + + @staticmethod + def UserUpdate(DEVICE=vars.UserUpdate().device, PLATFORM=vars.UserUpdate().platform, OS=vars.UserUpdate().os, + VERSION=vars.UserUpdate().version): + takv = Takv() + takv.setdevice(DEVICE) + takv.setplatform(PLATFORM) + takv.setos(OS) + takv.setversion(VERSION) + return takv + + # os getter + def getos(self): + return self.os + + # os setter + def setos(self,os=0): + self.os=os + + + # version getter + def getversion(self): + return self.version + + # version setter + def setversion(self, version=0): + self.version=version + + + def getplatform(self): + return self.platform + + # platform setter + def setplatform(self, platform=0): + self.platform=platform + + # device getter + def getdevice(self): + return self.device + + # device setter + def setdevice(self, device=0): + self.device=device diff --git a/FreeTAKServer/model/FTSModel/Track.py b/FreeTAKServer/model/FTSModel/Track.py new file mode 100644 index 00000000..a6cb14bc --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Track.py @@ -0,0 +1,46 @@ +####################################################### +# +# Track.py +# Python implementation of the Class Track +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:09 AM +# Original author: Corvo +# +####################################################### +from FreeTAKServer.model.FTSModelVariables.TrackVariables import TrackVariables as vars + +class Track: + def __init__(self): + self.course = None + self.speed = None + + @staticmethod + def connection(COURSE = vars.connection().COURSE, SPEED = vars.connection().SPEED): + track = Track() + track.setcourse(COURSE) + track.setspeed(SPEED) + return track + + @staticmethod + def UserUpdate(SPEED=vars.UserUpdate().speed, COURSE=vars.UserUpdate().course): + track = Track() + track.setspeed(SPEED) + track.setcourse(COURSE) + return track + + # speed getter + def getspeed(self): + return self.speed + + # speed setter + def setspeed(self, speed=0): + self.speed=speed + + # course getter + def getcourse(self): + return self.course + + # course setter + def setcourse(self, course=0): + self.course=course + diff --git a/FreeTAKServer/model/FTSModel/Uid.py b/FreeTAKServer/model/FTSModel/Uid.py new file mode 100644 index 00000000..7e56e3d0 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Uid.py @@ -0,0 +1,23 @@ +from FreeTAKServer.model.FTSModelVariables.UidVariables import UidVariables as vars + +class Uid: + def __init__(self): + self.Droid = None + + @staticmethod + def connection(DROID = vars.connection().DROID): + uid = Uid() + uid.setDroid(DROID) + return uid + + @staticmethod + def UserUpdate(DROID=vars.UserUpdate().Droid): + uid = Uid() + uid.setDroid(DROID) + return uid + + def getDroid(self): + return self.Droid + + def setDroid(self, Droid = None): + self.Droid = Droid diff --git a/FreeTAKServer/model/FTSModel/Usericon.py b/FreeTAKServer/model/FTSModel/Usericon.py new file mode 100644 index 00000000..606c45e1 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/Usericon.py @@ -0,0 +1,29 @@ +####################################################### +# +# usericon.py +# Python implementation of the Class usericon +# Generated by Enterprise Architect +# Created on: 11-Feb-2020 11:08:08 AM +# Original author: Corvo +# +####################################################### +from FreeTAKServer.model.FTSModelVariables.UsericonVariables import UsericonVariables as vars + +class Usericon: + def __init__(self): + self.iconsetpath = None + + @staticmethod + def drop_point(iconsetpath=vars.drop_point().ICONSETPATH): + usericon = Usericon() + usericon.seticonsetpath(iconsetpath=iconsetpath) + return usericon + + # iconsetpath getter + def geticonsetpath(self): + return self.iconsetpath + + # iconsetpath setter + def seticonsetpath(self, iconsetpath=0): + self.iconsetpath=iconsetpath + diff --git a/FreeTAKServer/model/FTSModel/_Group.py b/FreeTAKServer/model/FTSModel/_Group.py new file mode 100644 index 00000000..3dac9207 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/_Group.py @@ -0,0 +1,32 @@ +from FreeTAKServer.model.FTSModelVariables._GroupVariables import _GroupVariables as vars + +class _Group: + def __init__(self): + self.name = None + self.role = None + + @staticmethod + def connection(NAME = vars.connection().NAME, ROLE = vars.connection().ROLE): + _group = _Group() + _group.setname(NAME) + _group.setrole(ROLE) + return _group + + @staticmethod + def UserUpdate(NAME=vars.UserUpdate().name, ROLE=vars.UserUpdate().role): + _group = _Group() + _group.setname(NAME) + _group.setrole(ROLE) + return _group + + def getrole(self): + return self.role + + def setrole(self, role): + self.role = role + + def getname(self): + return self.name + + def setname(self, name): + self.name = name diff --git a/FreeTAKServer/model/FTSModel/__init__.py b/FreeTAKServer/model/FTSModel/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/model/FTSModel/_medevac_ .py b/FreeTAKServer/model/FTSModel/_medevac_ .py new file mode 100644 index 00000000..c56b4b83 --- /dev/null +++ b/FreeTAKServer/model/FTSModel/_medevac_ .py @@ -0,0 +1,47 @@ +####################################################### +# +# _medevac_ .py +# Python implementation of the Class _medevac_ +# Generated by Enterprise Architect +# Created on: 13-Apr-2020 4:07:52 PM +# Original author: Corvo +# +####################################################### + +class _medevac_ : + """the medevac class is used to describe a case of someone in need to be evacuated + """ +# default constructor def __init__(self): + + __litter = "1" + __freq = "0.0" + __terrain_none = "true" + __zone_prot_selection = "0" + __Title = "" + __Priority = "1" + __medline_remarks = "" + __Security = "" + __routine = "" + __equipment_none = "" + __hlz_marking = "" + __casevac = "" + __urgent = "" + +class _medevac_ : + """the medevac class is used to describe a case of someone in need to be evacuated + """ +# default constructor def __init__(self): + + __litter = "1" + __freq = "0.0" + __terrain_none = "true" + __zone_prot_selection = "0" + __Title = "" + __Priority = "1" + __medline_remarks = "" + __Security = "" + __routine = "" + __equipment_none = "" + __hlz_marking = "" + __casevac = "" + __urgent = "" \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/ChatVariables.py b/FreeTAKServer/model/FTSModelVariables/ChatVariables.py new file mode 100644 index 00000000..d25a0617 --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/ChatVariables.py @@ -0,0 +1,16 @@ +class ChatVariables: + def __init__(self): + self.SENDERCALLSIGN = None + self.ID = None + self.PARENT = None + self.CHATROOM = None + self.GROUPOWNER = None + + @classmethod + def geochat(cls): + cls.SENDERCALLSIGN = 'SERVER-UID' + cls.ID = "All Chat Rooms" + cls.PARENT = None + cls.CHATROOM = "All Chat Rooms" + cls.GROUPOWNER = "false" + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/ChatgrpVariables.py b/FreeTAKServer/model/FTSModelVariables/ChatgrpVariables.py new file mode 100644 index 00000000..8d41e1fd --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/ChatgrpVariables.py @@ -0,0 +1,13 @@ +class ChatgrpVariables: + + def __init__(self): + self.ID = None + self.UID0 = None + self.UID1 = None + + @classmethod + def geochat(cls): + cls.ID = "SERVER-UID" + cls.UID1 = "All Chat Rooms" + cls.UID0 = "SERVER-UID" + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/ColorVariables.py b/FreeTAKServer/model/FTSModelVariables/ColorVariables.py new file mode 100644 index 00000000..162f6230 --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/ColorVariables.py @@ -0,0 +1,8 @@ +class ColorVariables: + def __init__(self): + ARGB = None + + @classmethod + def drop_point(cls): + cls.ARGB = "-1" + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/ContactVariables.py b/FreeTAKServer/model/FTSModelVariables/ContactVariables.py new file mode 100644 index 00000000..063fcb79 --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/ContactVariables.py @@ -0,0 +1,50 @@ +class ContactVariables: + def __init__(self): + self.CALLSIGN = None + self.ENDPOINT = None + self.ICONSETPATH = None + self.UID = None + self.NAME = None + + @classmethod + def connection(cls): + cls.CALLSIGN = None + cls.ENDPOINT = None + cls.ICONSETPATH = None + cls.UID = None + cls.NAME = None + return cls + + @classmethod + def drop_point(cls): + cls.CALLSIGN = "DEFAULT" + cls.ENDPOINT = None + cls.ICONSETPATH = None + cls.UID = None + cls.NAME = None + return cls + + @classmethod + def geochat(cls): + cls.CALLSIGN = "DEFAULT" + cls.ENDPOINT = None + cls.ICONSETPATH = None + cls.UID = None + cls.NAME = None + return cls + + @classmethod + def emergency_on(cls): + cls.CALLSIGN = None + cls.ENDPOINT = None + cls.ICONSETPATH = None + cls.UID = None + cls.NAME = None + return cls + + @classmethod + def UserUpdate(cls): + cls.endpoint = None + cls.phone = None + cls.callsign = None + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/DestVariables.py b/FreeTAKServer/model/FTSModelVariables/DestVariables.py new file mode 100644 index 00000000..2ca6e908 --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/DestVariables.py @@ -0,0 +1,13 @@ +class DestVariables: + def __init__(self): + self.CALLSIGN = None + + @classmethod + def geochat(cls): + cls.CALLSIGN = None + return cls + + @classmethod + def other(cls): + cls.CALLSIGN = None + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/DetailVariables.py b/FreeTAKServer/model/FTSModelVariables/DetailVariables.py new file mode 100644 index 00000000..f807528c --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/DetailVariables.py @@ -0,0 +1,10 @@ +class DetailVariables: + def __init__(self): + self.TypeDict = { + 'geochat':self.GeoChat, + 'connection': self.Connection, + 'ping': self.Ping, + 'other': self.Other, + 'emergencyOn': self.emergencyOn, + 'emergencyOff': self.emergencyOff + } diff --git a/FreeTAKServer/model/FTSModelVariables/EmergencyVariables.py b/FreeTAKServer/model/FTSModelVariables/EmergencyVariables.py new file mode 100644 index 00000000..372d3f60 --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/EmergencyVariables.py @@ -0,0 +1,20 @@ +class EmergencyVariables: + def __init__(self): + self.TYPE = None + self.ALERT = None + # if true the Emergency beacon is canceled + self.CANCEL = None + + @classmethod + def emergency_on(cls): + cls.CANCEL = None + cls.ALERT = None + cls.TYPE = None + cls.INTAG = None + return cls + + @classmethod + def emergency_off(cls): + cls.CANCEL = None + cls.INTAG = None + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/EventVariables.py b/FreeTAKServer/model/FTSModelVariables/EventVariables.py new file mode 100644 index 00000000..2e2e754a --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/EventVariables.py @@ -0,0 +1,122 @@ +class EventVariables: + + @classmethod + def drop_point(cls): + cls.VERSIONNUM = '2.0' + cls.UID = 'RANDOM' + cls.TYPE = "DEFAULT" + cls.HOW = "h-g-i-g-o" + cls.TIME = None + cls.START = None + cls.STALE = None + return cls + + @classmethod + def geochat(cls): + cls.VERSIONNUM = '2.0' + cls.UID = None + cls.TYPE = "b-t-f" + cls.HOW = 'h-g-i-g-o' + cls.TIME = None + cls.START = None + cls.STALE = None + return cls + + @classmethod + def other(cls): + cls.VERSIONNUM = '2.0' + cls.UID = 'RANDOM' + cls.TYPE = "DEFAULT" + cls.HOW = None + cls.TIME = None + cls.START = None + cls.STALE = None + return cls + + @classmethod + def FederatedCoT(cls): + cls.VERSIONNUM = '2.0' + cls.UID = 'RANDOM' + cls.TYPE = "DEFAULT" + cls.HOW = None + cls.TIME = None + cls.START = None + cls.STALE = None + return cls + + @classmethod + def emergency_on(cls): + cls.VERSIONNUM = '2.0' + cls.UID = 'RANDOM' + cls.TYPE = "DEFAULT" + cls.HOW = None + cls.TIME = None + cls.START = None + cls.STALE = None + return cls + + @classmethod + def emergency_off(cls): + cls.VERSIONNUM = '2.0' + cls.UID = 'RANDOM' + cls.TYPE = "DEFAULT" + cls.HOW = None + cls.TIME = None + cls.START = None + cls.STALE = None + return cls + + @classmethod + def connection(cls): + cls.VERSIONNUM = '2.0' + cls.UID = 'RANDOM' + cls.TYPE = "DEFAULT" + cls.HOW = None + cls.TIME = None + cls.START = None + cls.STALE = None + return cls + + @classmethod + def ping(cls): + cls.VERSIONNUM = '2.0' + cls.UID = 'RANDOM' + cls.TYPE = "DEFAULT" + cls.HOW = None + cls.TIME = None + cls.START = None + cls.STALE = None + return cls + + @classmethod + def disconnect(cls): + cls.uid = None + cls.version = '2.0' + cls.type = 't-x-d-d' + cls.time = None + cls.start = None + cls.stale = None + cls.how = 'h-g-i-g-o' + return cls + + @classmethod + def takPong(cls): + cls.version = '2.0' + cls.uid = 'takPong' + cls.type = 't-x-c-t-r' + cls.how = 'h-g-i-g-o' + cls.time = None + cls.start = None + cls.stale = None + return cls + + @classmethod + def UserUpdate(cls): + cls.version = None + cls.uid = None + cls.type = None + cls.how = None + cls.time = None + cls.start = None + cls.stale = None + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/LinkVariables.py b/FreeTAKServer/model/FTSModelVariables/LinkVariables.py new file mode 100644 index 00000000..383e32a0 --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/LinkVariables.py @@ -0,0 +1,40 @@ +class LinkVariables: + def __init__(self): + self.UID = None + self.RELATION = None + self.PRODUCTIONTIME = None + self.TYPE = None + self.PARENTCALLSIGN = None + + @classmethod + def drop_point(cls): + cls.UID = "DEFAULT" + cls.TYPE = "a-f-G-U-C" + cls.PARENTCALLSIGN = "DEFAULT" + cls.RELATION = "p-p" + cls.PRODUCTIONTIME = None + return cls + + @classmethod + def geochat(cls): + cls.UID = "SERVER-UID" + cls.TYPE = "a-f-G-U-C-I" + cls.PARENTCALLSIGN = None + cls.RELATION = "p-p" + return cls + + @classmethod + def emergency_on(cls): + cls.UID = "DEFAULT" + cls.TYPE = "a-f-G-U-C" + cls.PARENTCALLSIGN = "DEFAULT" + cls.RELATION = "p-p" + cls.PRODUCTIONTIME = None + return cls + + @classmethod + def disconnect(cls): + cls.uid = None + cls.type = "a-f-G-U-C" + cls.relation = "p-p" + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/MartiVariables.py b/FreeTAKServer/model/FTSModelVariables/MartiVariables.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/model/FTSModelVariables/PointVariables.py b/FreeTAKServer/model/FTSModelVariables/PointVariables.py new file mode 100644 index 00000000..952a8a1d --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/PointVariables.py @@ -0,0 +1,7 @@ +class PointVariables: + def __init__(self): + self.LE = "9999999.0" + self.CE = "9999999.0" + self.HAE = "9999999.0" + self.LON = "0" + self.LAT = "0" \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/PrecisionlocationVariables.py b/FreeTAKServer/model/FTSModelVariables/PrecisionlocationVariables.py new file mode 100644 index 00000000..41ccabe9 --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/PrecisionlocationVariables.py @@ -0,0 +1,22 @@ +class PrecisionlocationVariables: + def __init__(self): + self.ALTSRC = None + self.GEOPOINTSRC = None + + @classmethod + def drop_point(cls): + cls.ALTSRC = '???' + cls.GEOPOINTSRC = None + return cls + + @classmethod + def connection(cls): + cls.ALTSRC = None + cls.GEOPOINTSRC = None + return cls + + @classmethod + def UserUpdate(cls): + cls.altsrc = None + cls.geopointsrc = None + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/RemarksVariables.py b/FreeTAKServer/model/FTSModelVariables/RemarksVariables.py new file mode 100644 index 00000000..cb30f5a5 --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/RemarksVariables.py @@ -0,0 +1,23 @@ +class RemarksVariables: + def __init__(self): + self.TIME = None + self.SOURCE = None + self.SOURCEID = None + self.INTAG = None + + @classmethod + def drop_point(cls): + cls.TIME = None + cls.SOURCE = None + cls.SOURCEID = None + cls.INTAG = None + return cls + + @classmethod + def geochat(cls): + cls.TIME = None + cls.SOURCE = 'SERVER' + cls.SOURCEID = None + cls.INTAG = 'DEFAULT' + cls.TO = 'All Chat Rooms' + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/ServerdestinationVariables.py b/FreeTAKServer/model/FTSModelVariables/ServerdestinationVariables.py new file mode 100644 index 00000000..a0db2ec8 --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/ServerdestinationVariables.py @@ -0,0 +1,8 @@ +class ServerdestionationVariables: + def __init__(self): + self.DESTINATIONS = None + + @classmethod + def geochat(cls): + cls.DESTINATIONS = None + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/SummaryVariables.py b/FreeTAKServer/model/FTSModelVariables/SummaryVariables.py new file mode 100644 index 00000000..dcf0ce15 --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/SummaryVariables.py @@ -0,0 +1,9 @@ +class SummaryVariables: + def __init__(self): + self.INTAG = None + + @classmethod + def drop_point(cls): + #appears to be present on points shared over gottena + cls.INTAG = None + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/TakvVariables.py b/FreeTAKServer/model/FTSModelVariables/TakvVariables.py new file mode 100644 index 00000000..459cf9f3 --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/TakvVariables.py @@ -0,0 +1,22 @@ +class TakvVariables: + def __init__(self): + self.VERSION = None + self.PLATFORM = None + self.DEVICE = None + self.OS = None + + @classmethod + def connection(cls): + cls.VERSION = None + cls.PLATFORM = None + cls.DEVICE = None + cls.OS = None + return cls + + @classmethod + def UserUpdate(cls): + cls.device = None + cls.platform = None + cls.os = None + cls.version = None + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/TrackVariables.py b/FreeTAKServer/model/FTSModelVariables/TrackVariables.py new file mode 100644 index 00000000..f230c0ff --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/TrackVariables.py @@ -0,0 +1,16 @@ +class TrackVariables: + def __init__(self): + self.COURSE = None + self.SPEED = None + + @classmethod + def connection(cls): + cls.SPEED = None + cls.COURSE = None + return cls + + @classmethod + def UserUpdate(cls): + cls.speed = None + cls.course = None + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/UidVariables.py b/FreeTAKServer/model/FTSModelVariables/UidVariables.py new file mode 100644 index 00000000..0213d8da --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/UidVariables.py @@ -0,0 +1,13 @@ +class UidVariables: + def __init__(self): + self.DROID = None + + @classmethod + def connection(cls): + cls.DROID = None + return cls + + @classmethod + def UserUpdate(cls): + cls.Droid = None + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/UsericonVariables.py b/FreeTAKServer/model/FTSModelVariables/UsericonVariables.py new file mode 100644 index 00000000..7ca2baa0 --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/UsericonVariables.py @@ -0,0 +1,8 @@ +class UsericonVariables: + def __init__(self): + self.ICONSETPATH = "DEFAULT" + + @classmethod + def drop_point(cls): + cls.ICONSETPATH = "DEFAULT" + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/_GroupVariables.py b/FreeTAKServer/model/FTSModelVariables/_GroupVariables.py new file mode 100644 index 00000000..2be0cba5 --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/_GroupVariables.py @@ -0,0 +1,16 @@ +class _GroupVariables: + def __init__(self): + self.NAME = None + self.ROLE = None + + @classmethod + def connection(cls): + cls.NAME = None + cls.ROLE = None + return cls + + @classmethod + def UserUpdate(cls): + cls.name = None + cls.role = None + return cls \ No newline at end of file diff --git a/FreeTAKServer/model/FTSModelVariables/__init__.py b/FreeTAKServer/model/FTSModelVariables/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/model/FTSModelVariables/statusVariables.py b/FreeTAKServer/model/FTSModelVariables/statusVariables.py new file mode 100644 index 00000000..c7c30ade --- /dev/null +++ b/FreeTAKServer/model/FTSModelVariables/statusVariables.py @@ -0,0 +1,21 @@ +class statusVariables: + def __init__(self): + self.BATTERY = None + self.READINESS = None + + @classmethod + def drop_point(cls): + cls.BATTERY = None + cls.READINESS = "true" + return cls + + @classmethod + def connection(cls): + cls.BATTERY = '100' + cls.READINESS = "true" + return cls + + @classmethod + def UserUpdate(cls): + cls.battery = None + return cls diff --git a/FreeTAKServer/model/FilterGroup.py b/FreeTAKServer/model/FilterGroup.py new file mode 100644 index 00000000..d6711efd --- /dev/null +++ b/FreeTAKServer/model/FilterGroup.py @@ -0,0 +1,47 @@ +class FilterGroup: + def __init__(self): + # an array of pipes to receive data from + self.sources = [] + + # an array of pipes to send data too + self.receivers = [] + + # an array of types of CoT which can be received by this group + self.allowedType = ['*'] + + # an array of types of CoT which can't be received by this group + self.rejectedType = [] + + def add_source(self, source): + self.sources.append(source) + + def remove_source(self, source): + self.sources.remove(source) + + def get_sources(self): + return self.receivers + + def add_receiver(self, source): + self.receivers.append(source) + + def remove_receiver(self, source): + self.receivers.remove(source) + + def get_receivers(self): + return self.receivers + + def add_allowed_type(self, type): + self.allowedType.append(type) + + def remove_allowed_type(self, type): + self.allowedType.remove(type) + + def get_allowed_types(self): + return self.allowedType + + def check_if_type_is_allowed(self, type): + if type in self.allowedType and type not in self.rejectedType or self.allowedType == ['*'] and type not in self.rejectedType: + return True + + else: + return False \ No newline at end of file diff --git a/FreeTAKServer/model/RawCoT.py b/FreeTAKServer/model/RawCoT.py new file mode 100644 index 00000000..09109d04 --- /dev/null +++ b/FreeTAKServer/model/RawCoT.py @@ -0,0 +1,20 @@ +####################################################### +# +# RawCoT.py +# Python implementation of the Class RawCoT +# Generated by Enterprise Architect +# Created on: 21-May-2020 9:47:30 AM +# Original author: Natha Paquette +# +####################################################### + + +class RawCoT: + def __init__(self): + self.type = "RawCoT" + self.CoTType = "" + self.clientInformation = "" + self.xmlString = b"" + self.disconnect = 0 + self.status = '' + self.protocol = 'xml' diff --git a/FreeTAKServer/model/RawConnectionInformation.py b/FreeTAKServer/model/RawConnectionInformation.py new file mode 100644 index 00000000..77a47bcb --- /dev/null +++ b/FreeTAKServer/model/RawConnectionInformation.py @@ -0,0 +1,17 @@ +####################################################### +# +# RawConnectionInformation.py +# Python implementation of the Class RawConnectionInformation +# Generated by Enterprise Architect +# Created on: 21-May-2020 9:47:28 AM +# Original author: Natha Paquette +# +####################################################### + + +class RawConnectionInformation: + def __init__(self): + self.type = 'RawConnectionInformation' + self.xmlString = "" + self.ip = "" + self.socket = "" diff --git a/FreeTAKServer/model/ReceiveConnectionsProcess.py b/FreeTAKServer/model/ReceiveConnectionsProcess.py new file mode 100644 index 00000000..3abc7d92 --- /dev/null +++ b/FreeTAKServer/model/ReceiveConnectionsProcess.py @@ -0,0 +1,13 @@ +####################################################### +# +# ReceiveConnectionsProcess.py +# Python implementation of the Class ReceiveConnectionsProcess +# Generated by Enterprise Architect +# Created on: 21-May-2020 9:47:41 AM +# Original author: Natha Paquette +# +####################################################### + +class ReceiveConnectionsProcess: + def __init__(self): + self.receiveConnections = "" diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Archive.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Archive.py new file mode 100644 index 00000000..c39b1a15 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Archive.py @@ -0,0 +1,19 @@ +####################################################### +# +# Archive.py +# Python implementation of the Class Archive +# Generated by Enterprise Architect +# Created on: 26-Sep-2020 9:41:27 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column, ForeignKey +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy.orm import relationship + + +class Archive(Base): + + __tablename__ = 'Archive' + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + Detail = relationship("Detail", back_populates="archive") \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Chat.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Chat.py new file mode 100644 index 00000000..4037c596 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Chat.py @@ -0,0 +1,29 @@ +####################################################### +# +# chat.py +# Python implementation of the Class chat +# Generated by Enterprise Architect +# Created on: 28-Sep-2020 10:48:13 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column, ForeignKey +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy.orm import relationship +from sqlalchemy import String + +class Chat(Base): + # default constructor def __init__(self): + __tablename__ = "Chat" + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + Detail = relationship("Detail", back_populates="chat") + # TBD: the callsign of the receiver? + chatroom = Column(String) + # TBD, + groupOwner = Column(String) + # TBD: the unique ID of the sender? + id = Column(String) + # the group where thise chat is attached + parent = Column(String) + # the call sign of the sender + senderCallsign = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/CoTTableAbstract.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/CoTTableAbstract.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Color.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Color.py new file mode 100644 index 00000000..fcdda77e --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Color.py @@ -0,0 +1,19 @@ +####################################################### +# +# Color.py +# Python implementation of the Class Color +# Generated by Enterprise Architect +# Created on: 26-Sep-2020 9:41:35 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column, ForeignKey +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String + + +class Color(Base): +# default constructor def __init__(self): + __tablename__ = "Color" + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + argb = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Contact.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Contact.py new file mode 100644 index 00000000..36fe2bcb --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Contact.py @@ -0,0 +1,44 @@ +####################################################### +# +# Contact.py +# Python implementation of the Class Contact +# Generated by Enterprise Architect +# Created on: 26-Sep-2020 9:41:39 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column, ForeignKey +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String + + +class Contact(Base): +# default constructor def __init__(self): + + __tablename__ = "Contact" + + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + + # The unit's voice call sign + callsign = Column(String) + # DSN number for this element (if applicable) + dsn = Column(String) + # e-mail address for this element (if applicable) + email = Column(String) + # TBD + endpoint = Column(String) + # The frequency (in MHz) on which the unit may be contacted via voice. + freq = Column(String) + # DNS-resolvable host name + hostname = Column(String) + iconsetpath = Column(String) + # Amplifies the radio frequency information provided. Contains the modulation + # type for the communication. (Coding tbd, should cover complex modulations such + # as SINCGARS hopping, csma, etc...) am|fm + modulation = Column(String) + # Phone number for this element (if applicable) + phone = Column(String) + # Version tag for this sub schema. Necessary to ensure upward compatibility with + # future revisions. + version = Column(String) + diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Dest.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Dest.py new file mode 100644 index 00000000..f086e113 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Dest.py @@ -0,0 +1,23 @@ +####################################################### +# +# dest.py +# Python implementation of the Class dest +# Generated by Enterprise Architect +# Created on: 26-Sep-2020 9:41:48 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column, ForeignKey +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import Integer +from sqlalchemy import String + + +class Dest(Base): +# default constructor def __init__(self): + + # the call sign of the destination + __tablename__ = "Dest" + PrimaryKey = Column(Integer, primary_key=True, autoincrement=True) + OwnerPrimaryKey = Column(String, ForeignKey("Marti.PrimaryKey")) + callsign = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Detail.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Detail.py new file mode 100644 index 00000000..4bece172 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Detail.py @@ -0,0 +1,57 @@ +####################################################### +# +# Detail.py +# Python implementation of the Class Detail +# Generated by Enterprise Architect +# Created on: 26-Sep-2020 9:41:25 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column, ForeignKey +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String +from sqlalchemy.orm import relationship +import FreeTAKServer.model.SQLAlchemy.CoTTables.Archive +import FreeTAKServer.model.SQLAlchemy.CoTTables._Group +import FreeTAKServer.model.SQLAlchemy.CoTTables.Chat +import FreeTAKServer.model.SQLAlchemy.CoTTables.Color +import FreeTAKServer.model.SQLAlchemy.CoTTables.Contact +import FreeTAKServer.model.SQLAlchemy.CoTTables.Dest +import FreeTAKServer.model.SQLAlchemy.CoTTables.Emergency +import FreeTAKServer.model.SQLAlchemy.CoTTables.Link +import FreeTAKServer.model.SQLAlchemy.CoTTables.Marti +import FreeTAKServer.model.SQLAlchemy.CoTTables.Precisionlocation +import FreeTAKServer.model.SQLAlchemy.CoTTables.Remarks +import FreeTAKServer.model.SQLAlchemy.CoTTables.Serverdestination +import FreeTAKServer.model.SQLAlchemy.CoTTables.Status +import FreeTAKServer.model.SQLAlchemy.CoTTables.Summary +import FreeTAKServer.model.SQLAlchemy.CoTTables.Takv +import FreeTAKServer.model.SQLAlchemy.CoTTables.Track +import FreeTAKServer.model.SQLAlchemy.CoTTables.Uid +import FreeTAKServer.model.SQLAlchemy.CoTTables.Usericon + + + +class Detail(Base): +# default constructor def __init__(self): + __tablename__ = 'Detail' + PrimaryKey = Column(ForeignKey("Event.uid"), primary_key=True) + xmlString = Column(String) + archive = relationship("Archive", uselist=False) + #_group = relationship("_Group", uselist=False, back_populates="parent") + chat = relationship("Chat", uselist=False) + color = relationship("Color", uselist=False) + contact = relationship("Contact", uselist=False) + emergency = relationship("Emergency", uselist=False) + link = relationship("Link", uselist=False) + marti = relationship("Marti", uselist=False) + precisionlocation = relationship("Precisionlocation", uselist=False) + remarks = relationship("Remarks", uselist=False) + serverdestination = relationship("Serverdestination", uselist=False) + status = relationship("Status", uselist=False) + summary = relationship("Summary", uselist=False) + takv = relationship("Takv", uselist=False) + track = relationship("Track", uselist=False) + uid = relationship("Uid", uselist=False) + usericon = relationship("Usericon", uselist=False) + diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Emergency.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Emergency.py new file mode 100644 index 00000000..5d8ce0d2 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Emergency.py @@ -0,0 +1,25 @@ +####################################################### +# +# emergency.py +# Python implementation of the Class emergency +# Generated by Enterprise Architect +# Created on: 28-Sep-2020 10:48:15 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String +from sqlalchemy import ForeignKey +from sqlalchemy.orm import relationship + + +class Emergency(Base): + __tablename__ = "Emergency" + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + Detail = relationship("Detail", back_populates="emergency") + Alert = Column(String) + # if true the emergency beacon is canceled + cancel = Column(String) + # default constructor def __init__(self): + type = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Link.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Link.py new file mode 100644 index 00000000..eeba7481 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Link.py @@ -0,0 +1,47 @@ +####################################################### +# +# Link.py +# Python implementation of the Class Link +# Generated by Enterprise Architect +# Created on: 26-Sep-2020 9:41:33 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column, ForeignKey +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String +from sqlalchemy.orm import relationship + + +class Link(Base): +# default constructor def __init__(self): + __tablename__ = "Link" + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + Detail = relationship("Detail", back_populates="link") + #PrimaryKey = Column(ForeignKey('detail.uid'), primary_key=True) + # Internet Media type of the referenced object. If the link is to a CoT event, + # the mime attribute is optional and its type may be application/xml or text/xml + # as described in RFC 3023, "XML Media Types", or the unregistered type, + # application/cot+xml. If the link is to an arbitrary resource, the mime + # attribute is required and and appropriate Internet media type must be specified. + # Registered media types are managed by the IANA and are listed at http://www. + # iana.org/assignments/media-types/. + mime = Column(String) + parent_callsign = Column(String) + production_time = Column(String) + # The type of relationship (e.g, subject, object, indirect object) that this link + # describes. This is a hierarchy much like the event type field. + relation = Column(String) + # Remarks associated with this link. + remarks = Column(String) + # The CoT type of the referenced object. This is included because it is + # generally the key item needed in a tasking. + type = Column(String) + uid = Column(String) + # If present, this is a URL through which the linked object can be retrieved. + # If the URL is missing, then the object should be a periodic message (e.g., blue + # force track) that can be read from a CoT stream. + url = Column(String) + # Version tag for this sub schema. Neccessary to ensure upward compatibility + # with future revisions. + version = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Marti.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Marti.py new file mode 100644 index 00000000..8b66ddf8 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Marti.py @@ -0,0 +1,19 @@ +####################################################### +# +# Marti.py +# Python implementation of the Class Marti +# Generated by Enterprise Architect +# Created on: 26-Sep-2020 9:41:44 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column, ForeignKey +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy.orm import relationship + + +class Marti(Base): +# default constructor def __init__(self): + __tablename__ = "Marti" + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + dest = relationship("Dest", backref="owner") diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Point.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Point.py new file mode 100644 index 00000000..69df34cf --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Point.py @@ -0,0 +1,24 @@ +####################################################### +# +# Point.py +# Python implementation of the Class Point +# Generated by Enterprise Architect +# Created on: 26-Sep-2020 9:41:22 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String +from sqlalchemy import ForeignKey + + +class Point(Base): +# default constructor def __init__(self): + __tablename__ = "Point" + PrimaryKey = Column(ForeignKey("Event.uid"), primary_key=True) + ce = Column(String) + hae = Column(String) + lat = Column(String) + le = Column(String) + lon = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Precisionlocation.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Precisionlocation.py new file mode 100644 index 00000000..aa2ca716 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Precisionlocation.py @@ -0,0 +1,24 @@ +####################################################### +# +# Precisionlocation.py +# Python implementation of the Class Precisionlocation +# Generated by Enterprise Architect +# Created on: 26-Sep-2020 9:41:37 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column, ForeignKey +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String +from sqlalchemy.orm import relationship + + +class Precisionlocation(Base): +# default constructor def __init__(self): + + __tablename__ = "Precisionlocation" + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + Detail = relationship("Detail", back_populates="precisionlocation") + # TDB can be DTED0 or ??? + altsrc = Column(String) + geopointsrc = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Remarks.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Remarks.py new file mode 100644 index 00000000..efa94912 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Remarks.py @@ -0,0 +1,45 @@ +####################################################### +# +# Remarks.py +# Python implementation of the Class Remarks +# Generated by Enterprise Architect +# Created on: 26-Sep-2020 9:41:41 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column, ForeignKey +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String +from sqlalchemy.orm import relationship + + +class Remarks(Base): +# default constructor def __init__(self): + __tablename__ = "Remarks" + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + Detail = relationship("Detail", back_populates="remarks") + # Used to track a conversation thread. The format is a comma-separated list of + # freetext keywords. + # + # ex. keywords="debriefing" - Describes a conversation + # about debriefing + # ex. keywords="mission-A" - Describes a conversation + # about mission-A + # ex. keywords="tasking_B, subject_C" - Describes a conversation + # about tasking_B and subject_C + keywords = Column(String) + # Source specifies the sender’s UID – this is what is parsed by recipients to + # determine the sender, with the UID format being the fallback. + source = Column(String) + # the time of the remark was added to the CoT object + time = Column(String) + # Intended recipeint(s) of this remark information. Tentative field coding as + # follows: The to attribute may contain the UID of the entity to whom the message + # is addressed. (Implementors should expect that future versions of this sub + # schema will allow a comma separated list of UIDs.) Absense of an explict + # addressee means the message is broadcast. + # e.g. ANDROID-359975090666199 + to = Column(String) + # Version tag for this sub schema. Neccessary to ensure upward compatibility + # with future revisions. + version = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Serverdestination.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Serverdestination.py new file mode 100644 index 00000000..e4298e47 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Serverdestination.py @@ -0,0 +1,23 @@ +####################################################### +# +# serverdestination.py +# Python implementation of the Class serverdestination +# Generated by Enterprise Architect +# Created on: 28-Sep-2020 10:48:18 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column, ForeignKey +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String +from sqlalchemy.orm import relationship + + +class Serverdestination(Base): +# default constructor def __init__(self): + __tablename__ = "Serverdestination" + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + Detail = relationship("Detail", back_populates="serverdestination") + # string composed by IP:port: protocol:machineID. + # e.g. 192.168.0.103:4242:tcp:ANDROID-R52JB0CDC4E + destinations = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Status.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Status.py new file mode 100644 index 00000000..d20fb851 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Status.py @@ -0,0 +1,22 @@ +####################################################### +# +# Status.py +# Python implementation of the Class Status +# Generated by Enterprise Architect +# Created on: 26-Sep-2020 9:41:29 PM +# Original author: natha +# +from sqlalchemy import Column +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String +from sqlalchemy import ForeignKey + + +class Status(Base): +# default constructor def __init__(self): + __tablename__ = "Status" + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + # % of the battery on the phone + battery = Column(String) + # probably boolean to determine if ready or not + readiness = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Summary.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Summary.py new file mode 100644 index 00000000..75497eed --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Summary.py @@ -0,0 +1,22 @@ +####################################################### +# +# Summary.py +# Python implementation of the Class Summary +# Generated by Enterprise Architect +# Created on: 26-Sep-2020 9:41:46 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String +from sqlalchemy import ForeignKey +from sqlalchemy.orm import relationship + +class Summary(Base): +# default constructor def __init__(self): + __tablename__ = "Summary" + + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + Detail = relationship("Detail", back_populates="summary") + INTAG = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Takv.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Takv.py new file mode 100644 index 00000000..772f629f --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Takv.py @@ -0,0 +1,28 @@ +####################################################### +# +# takv.py +# Python implementation of the Class takv +# Generated by Enterprise Architect +# Created on: 28-Sep-2020 10:48:20 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column, ForeignKey +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String +from sqlalchemy.orm import relationship + + +class Takv(Base): +# default constructor def __init__(self): + __tablename__ = "Takv" + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + Detail = relationship("Detail", back_populates="takv") + # type of physical device + device = Column(String) + # the operating system running TAK + os = Column(String) + # the variant of TAK + platform = Column(String) + # the version of TAK running on the device + version = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Track.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Track.py new file mode 100644 index 00000000..5e7ed797 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Track.py @@ -0,0 +1,29 @@ +####################################################### +# +# track.py +# Python implementation of the Class track +# Generated by Enterprise Architect +# Created on: 28-Sep-2020 10:48:26 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String +from sqlalchemy import ForeignKey +from sqlalchemy.orm import relationship + +class Track(Base): +# default constructor def __init__(self): + __tablename__ = "Track" + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + Detail = relationship("Detail", back_populates="track") + course = Column(String) + # 1-sigma error on a Gaussian distribution associated with the course attribute + eCourse = Column(String) + # 1-sigma error on a Gaussian distribution associated with the slope attribute + eSlope = Column(String) + # 1-sigma error on a Gaussian distribution associated with the speed attribute + eSpeed = Column(String) + speed = Column(String) + version = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Uid.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Uid.py new file mode 100644 index 00000000..21d80d73 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Uid.py @@ -0,0 +1,23 @@ +####################################################### +# +# uid.py +# Python implementation of the Class uid +# Generated by Enterprise Architect +# Created on: 28-Sep-2020 10:48:30 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column, ForeignKey +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String +from sqlalchemy.orm import relationship + + +class Uid(Base): +# default constructor def __init__(self): + __tablename__ = "Uid" + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + Detail = relationship("Detail", back_populates="uid") + # TBD, maybe from Android? + Droid = Column(String) + version = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/Usericon.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/Usericon.py new file mode 100644 index 00000000..89211df8 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/Usericon.py @@ -0,0 +1,21 @@ +####################################################### +# +# Usericon.py +# Python implementation of the Class Usericon +# Generated by Enterprise Architect +# Created on: 26-Sep-2020 9:41:31 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String +from sqlalchemy import ForeignKey +from sqlalchemy.orm import relationship + +class Usericon(Base): +# default constructor def __init__(self): + __tablename__ = "Usericon" + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + Detail = relationship("Detail", back_populates="usericon") + iconsetpath = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/_Group.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/_Group.py new file mode 100644 index 00000000..ec422cd9 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/CoTTables/_Group.py @@ -0,0 +1,21 @@ +####################################################### +# +# _group.py +# Python implementation of the Class _group +# Generated by Enterprise Architect +# Created on: 28-Sep-2020 10:48:10 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column, ForeignKey +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy.orm import relationship + + +class _Group(): +# default constructor def __init__(self): + __tablename__ = "_Group" + PrimaryKey = Column(ForeignKey("Detail.PrimaryKey"), primary_key=True) + Detail = relationship("Detail", back_populates="_group") + name = "Yellow" + role = "Team Member" \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/CoTTables/__init__.py b/FreeTAKServer/model/SQLAlchemy/CoTTables/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/model/SQLAlchemy/DataPackage.py b/FreeTAKServer/model/SQLAlchemy/DataPackage.py new file mode 100644 index 00000000..24be228a --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/DataPackage.py @@ -0,0 +1,55 @@ +####################################################### +# +# DataPackage.py +# Python implementation of the Class DataPackage +# Generated by Enterprise Architect +# Created on: 21-Sep-2020 10:28:02 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column +from FreeTAKServer.model.SQLAlchemy.Root import Base, Root +from sqlalchemy import Integer +from sqlalchemy import String +from sqlalchemy import VARCHAR +from sqlalchemy import CHAR +from sqlalchemy import DateTime +from datetime import datetime as dt + +class DataPackage(Base, Root): + """ + sqlalchemy object of table of datapackages and their information + """ + + # Name of the table + __tablename__ = "DataPackages" + + #primary key + PrimaryKey = Column(Integer, primary_key = True, autoincrement=True) + + # UID of Package Creator + CreatorUid = Column(String) + + # 32-bit hash of datapackage + Hash = Column(VARCHAR) + + # data package keywords + Keywords = Column(CHAR, default='foobar') + + # File type + MIMEType = Column(String, default="[application/x-zip-compressed]") + + # Name of datapackage + Name = Column(String) + + # whether or not the data package is private 0 indicates false meaning it will be publicly broadcasted. + Privacy = Column(Integer, default=0) + + # the size in bytes of the datapackage + Size = Column(Integer) + + # the date time the datapackage was submitted + SubmissionDateTime = Column(DateTime, default=dt.utcnow()) + + # the call sign of the user who submitted the data package + SubmissionUser = Column(String) diff --git a/FreeTAKServer/model/SQLAlchemy/Event.py b/FreeTAKServer/model/SQLAlchemy/Event.py new file mode 100644 index 00000000..08530602 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/Event.py @@ -0,0 +1,28 @@ +####################################################### +# +# Event.py +# Python implementation of the Class Event +# Generated by Enterprise Architect +# Created on: 26-Sep-2020 12:18:51 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column +from FreeTAKServer.model.SQLAlchemy.Root import Base, Root +from FreeTAKServer.model.SQLAlchemy.CoTTables.Detail import Detail +from FreeTAKServer.model.SQLAlchemy.CoTTables.Point import Point +from sqlalchemy import String +from sqlalchemy.orm import relationship + + +class Event(Base, Root): +# default constructor def __init__(self): + + __tablename__ = "Event" + uid = Column(String, primary_key=True) + how = Column(String) + start = Column(String) + type = Column(String) + version = Column(String) + point = relationship("Point", uselist=False) + detail = relationship("Detail", uselist=False) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/Root.py b/FreeTAKServer/model/SQLAlchemy/Root.py new file mode 100644 index 00000000..2719bff3 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/Root.py @@ -0,0 +1,16 @@ +####################################################### +# +# Root.py +# Python implementation of the Class Root +# Generated by Enterprise Architect +# Created on: 21-Sep-2020 10:28:05 PM +# Original author: natha +# +####################################################### +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy import create_engine, Column, String, Integer + +Base = declarative_base() + +class Root: + uid = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/User.py b/FreeTAKServer/model/SQLAlchemy/User.py new file mode 100644 index 00000000..872f5130 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/User.py @@ -0,0 +1,22 @@ +####################################################### +# +# User.py +# Python implementation of the Class User +# Generated by Enterprise Architect +# Created on: 21-Sep-2020 10:28:08 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column +from FreeTAKServer.model.SQLAlchemy.Root import Base +from sqlalchemy import String + + +class User(Base): +# default constructor def __init__(self): + + """sqlalchemy object of table of connected users and their information + """ + __tablename__ = "User" + uid = Column(String(25), primary_key = True) + callsign = Column(String) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/UserConfiguration.py b/FreeTAKServer/model/SQLAlchemy/UserConfiguration.py new file mode 100644 index 00000000..e827f7c6 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/UserConfiguration.py @@ -0,0 +1,18 @@ +####################################################### +# +# UserConfiguration.py +# Python implementation of the Class UserConfiguration +# Generated by Enterprise Architect +# Created on: 21-Sep-2020 10:28:11 PM +# Original author: natha +# +####################################################### +from PSM.Column import Column +from PSM.Root import Root + +class UserConfiguration(Root): +# default constructor def __init__(self): + + Group = "" + Password = "" + UserName = "" \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/VideoStream.py b/FreeTAKServer/model/SQLAlchemy/VideoStream.py new file mode 100644 index 00000000..5bf2687e --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/VideoStream.py @@ -0,0 +1,34 @@ +####################################################### +# +# VideoStream.py +# Python implementation of the Class VideoStream +# Generated by Enterprise Architect +# Created on: 21-Sep-2020 10:23:44 PM +# Original author: natha +# +####################################################### +from sqlalchemy import Column, func +from FreeTAKServer.model.SQLAlchemy.Root import Base, Root +from sqlalchemy import Integer +from sqlalchemy import String +from sqlalchemy import DateTime + + +class VideoStream(Base, Root): +# default constructor def __init__(self): + + __tablename__ = "VideoStreams" + PrimaryKey = Column(Integer, primary_key = True, autoincrement=True) + Address = Column(String) + Alias = Column(String) + Buffer = Column(Integer, default=-1) + FullXmlString = Column(String) + IgnoreEmbeddedKlv = Column(String, default=False) + Path = Column(String, default=None) + Port = Column(Integer, default=-1) + PreferredMacAddress = Column(String, default=None) + Protocol = Column(String) + RoverPort = Column(Integer, default=-1) + RtspReliable = Column(Integer, default=0) + Timeout = Column(Integer) + Timestamp = Column(DateTime, default=func.now()) \ No newline at end of file diff --git a/FreeTAKServer/model/SQLAlchemy/__init__.py b/FreeTAKServer/model/SQLAlchemy/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/FreeTAKServer/model/SQLAlchemy/__init__.py @@ -0,0 +1 @@ + diff --git a/FreeTAKServer/model/ServiceObjects/CoTService.py b/FreeTAKServer/model/ServiceObjects/CoTService.py new file mode 100644 index 00000000..42e67749 --- /dev/null +++ b/FreeTAKServer/model/ServiceObjects/CoTService.py @@ -0,0 +1,9 @@ +from .CoTServiceVariables import CoTServiceVariables as vars + +class CoTService: + def __init__(self, CoTServiceIP = vars().CoTServiceIP, + CoTServicePort = vars().CoTServicePort, + CoTServiceStatus = vars().CoTServiceStatus): + self.CoTServiceIP = CoTServiceIP + self.CoTServicePort = CoTServicePort + self.CoTServiceStatus = CoTServiceStatus \ No newline at end of file diff --git a/FreeTAKServer/model/ServiceObjects/CoTServiceVariables.py b/FreeTAKServer/model/ServiceObjects/CoTServiceVariables.py new file mode 100644 index 00000000..bc585583 --- /dev/null +++ b/FreeTAKServer/model/ServiceObjects/CoTServiceVariables.py @@ -0,0 +1,7 @@ +from FreeTAKServer.controllers.configuration.MainConfig import MainConfig + +class CoTServiceVariables: + def __init__(self): + self.CoTServiceIP = "0.0.0.0" + self.CoTServicePort = MainConfig.CoTServicePort + self.CoTServiceStatus = "" \ No newline at end of file diff --git a/FreeTAKServer/model/ServiceObjects/DataPackageService.py b/FreeTAKServer/model/ServiceObjects/DataPackageService.py new file mode 100644 index 00000000..8e1eb014 --- /dev/null +++ b/FreeTAKServer/model/ServiceObjects/DataPackageService.py @@ -0,0 +1,9 @@ +from .DataPackageServiceVariables import DataPackageServiceVariables as vars + +class DataPackageService: + def __init__(self, DataPackageServiceIP = vars().DataPackageServiceIP, + DataPackageServicePort = vars().DataPackageServicePort, + DataPackageServiceStatus = vars().DataPackageServiceStatus): + self.DataPackageServiceIP = DataPackageServiceIP + self.DataPackageServicePort = DataPackageServicePort + self.DataPackageServiceStatus = DataPackageServiceStatus \ No newline at end of file diff --git a/FreeTAKServer/model/ServiceObjects/DataPackageServiceVariables.py b/FreeTAKServer/model/ServiceObjects/DataPackageServiceVariables.py new file mode 100644 index 00000000..3ad0310c --- /dev/null +++ b/FreeTAKServer/model/ServiceObjects/DataPackageServiceVariables.py @@ -0,0 +1,7 @@ +from FreeTAKServer.controllers.configuration.MainConfig import MainConfig + +class DataPackageServiceVariables: + def __init__(self): + self.DataPackageServiceIP = MainConfig.DataPackageServiceDefaultIP + self.DataPackageServicePort = 8080 + self.DataPackageServiceStatus = "" \ No newline at end of file diff --git a/FreeTAKServer/model/ServiceObjects/FTS.py b/FreeTAKServer/model/ServiceObjects/FTS.py new file mode 100644 index 00000000..7299a16b --- /dev/null +++ b/FreeTAKServer/model/ServiceObjects/FTS.py @@ -0,0 +1,10 @@ +from .FTSVariables import FTSVariables as vars +from .CoTService import CoTService +from .DataPackageService import DataPackageService +from .RestAPIService import RestAPIService + +class FTS: + def __init__(self): + self.CoTService = CoTService() + self.DataPackageService = DataPackageService() + self.RestAPIService = RestAPIService() \ No newline at end of file diff --git a/FreeTAKServer/model/ServiceObjects/FTSVariables.py b/FreeTAKServer/model/ServiceObjects/FTSVariables.py new file mode 100644 index 00000000..a1e53292 --- /dev/null +++ b/FreeTAKServer/model/ServiceObjects/FTSVariables.py @@ -0,0 +1,4 @@ +class FTSVariables: + + def __init__(self): + pass diff --git a/FreeTAKServer/model/ServiceObjects/RestAPIService.py b/FreeTAKServer/model/ServiceObjects/RestAPIService.py new file mode 100644 index 00000000..fa48d186 --- /dev/null +++ b/FreeTAKServer/model/ServiceObjects/RestAPIService.py @@ -0,0 +1,8 @@ +from .RestAPIServiceVariables import RestAPIServiceVariables as vars + +class RestAPIService: + def __init__(self, IP = vars().RestAPIServiceIP, Port = vars().RestAPIServicePort, Status = vars().RestAPIServiceStatus): + self.RestAPIServiceIP = IP + self.RestAPIServicePort = Port + self.RestAPIServiceStatus = Status + \ No newline at end of file diff --git a/FreeTAKServer/model/ServiceObjects/RestAPIServiceVariables.py b/FreeTAKServer/model/ServiceObjects/RestAPIServiceVariables.py new file mode 100644 index 00000000..ac72d003 --- /dev/null +++ b/FreeTAKServer/model/ServiceObjects/RestAPIServiceVariables.py @@ -0,0 +1,5 @@ +class RestAPIServiceVariables: + def __init__(self): + self.RestAPIServiceIP = "127.0.0.1" + self.RestAPIServicePort = 19023 + self.RestAPIServiceStatus = "" \ No newline at end of file diff --git a/FreeTAKServer/model/ServiceObjects/__init__.py b/FreeTAKServer/model/ServiceObjects/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/model/SimpleClient.py b/FreeTAKServer/model/SimpleClient.py new file mode 100644 index 00000000..ccfeb9d1 --- /dev/null +++ b/FreeTAKServer/model/SimpleClient.py @@ -0,0 +1,7 @@ +from .SimpleClientVariables import SimpleClientVariables as vars + +class SimpleClient: + def __init__(self, IP = vars().IP, CALLSIGN = vars().CALLSIGN, TEAM = vars().TEAM): + self.ip = IP + self.callsign = CALLSIGN + self.team = TEAM \ No newline at end of file diff --git a/FreeTAKServer/model/SimpleClientVariables.py b/FreeTAKServer/model/SimpleClientVariables.py new file mode 100644 index 00000000..c824d879 --- /dev/null +++ b/FreeTAKServer/model/SimpleClientVariables.py @@ -0,0 +1,5 @@ +class SimpleClientVariables: + def __init__(self): + self.IP = '0.0.0.0' + self.CALLSIGN = 'UNKNOWN' + self.TEAM = 'DEFAULT' \ No newline at end of file diff --git a/FreeTAKServer/model/SpecificCoT/SendDisconnect.py b/FreeTAKServer/model/SpecificCoT/SendDisconnect.py new file mode 100644 index 00000000..95b70bc8 --- /dev/null +++ b/FreeTAKServer/model/SpecificCoT/SendDisconnect.py @@ -0,0 +1,5 @@ +from .SpecificCoTAbstract import SpecificCoTAbstract +class SendDisconnect(SpecificCoTAbstract): + def __init__(self): + self.define_variables() + self.setType("Disconnect") \ No newline at end of file diff --git a/FreeTAKServer/model/SpecificCoT/SendDropPoint.py b/FreeTAKServer/model/SpecificCoT/SendDropPoint.py new file mode 100644 index 00000000..a15de6af --- /dev/null +++ b/FreeTAKServer/model/SpecificCoT/SendDropPoint.py @@ -0,0 +1,6 @@ +from .SpecificCoTAbstract import SpecificCoTAbstract + +class SendDropPoint(SpecificCoTAbstract): + def __init__(self): + self.define_variables() + self.setType("DropPoint") \ No newline at end of file diff --git a/FreeTAKServer/model/SpecificCoT/SendEmergency.py b/FreeTAKServer/model/SpecificCoT/SendEmergency.py new file mode 100644 index 00000000..b14b92c2 --- /dev/null +++ b/FreeTAKServer/model/SpecificCoT/SendEmergency.py @@ -0,0 +1,20 @@ +from .SpecificCoTAbstract import SpecificCoTAbstract + +class SendEmergency(SpecificCoTAbstract): + def __init__(self): + self.define_variables() + self.setType('Emergency') + self.setPlaceInternalArray(True) + self.setStatus('') + + def setPlaceInternalArray(self, placeInternalArray): + self.placeInternalArray = placeInternalArray + + def getPlaceInternalArray(self): + return self.placeInternalArray + + def setStatus(self, status): + self.status = status + + def getStatus(self): + return self.status diff --git a/FreeTAKServer/model/SpecificCoT/SendFederatedCoT.py b/FreeTAKServer/model/SpecificCoT/SendFederatedCoT.py new file mode 100644 index 00000000..3094ddb6 --- /dev/null +++ b/FreeTAKServer/model/SpecificCoT/SendFederatedCoT.py @@ -0,0 +1,6 @@ +from .SpecificCoTAbstract import SpecificCoTAbstract + +class SendFederatedCoT(SpecificCoTAbstract): + def __init__(self): + self.define_variables() + self.setType("FederatedCoT") diff --git a/FreeTAKServer/model/SpecificCoT/SendGeoChat.py b/FreeTAKServer/model/SpecificCoT/SendGeoChat.py new file mode 100644 index 00000000..db07dc71 --- /dev/null +++ b/FreeTAKServer/model/SpecificCoT/SendGeoChat.py @@ -0,0 +1,6 @@ +from .SpecificCoTAbstract import SpecificCoTAbstract + +class SendGeoChat(SpecificCoTAbstract): + def __init__(self): + self.define_variables() + self.setType("GeoChat") \ No newline at end of file diff --git a/FreeTAKServer/model/SpecificCoT/SendHealthCheck.py b/FreeTAKServer/model/SpecificCoT/SendHealthCheck.py new file mode 100644 index 00000000..e8346585 --- /dev/null +++ b/FreeTAKServer/model/SpecificCoT/SendHealthCheck.py @@ -0,0 +1,4 @@ +class SendHealthCheck: + def __init__(self): + self.xmlString = '' + self.clientInformation = '' \ No newline at end of file diff --git a/FreeTAKServer/model/SpecificCoT/SendInvalidCoT.py b/FreeTAKServer/model/SpecificCoT/SendInvalidCoT.py new file mode 100644 index 00000000..e96c46f4 --- /dev/null +++ b/FreeTAKServer/model/SpecificCoT/SendInvalidCoT.py @@ -0,0 +1,6 @@ +class SendInvalidCoT: + def __init__(self): + self.type = 'invalid' + self.invalid = True + self.clientInformation = '' + self.xmlString = b'' \ No newline at end of file diff --git a/FreeTAKServer/model/SpecificCoT/SendOther.py b/FreeTAKServer/model/SpecificCoT/SendOther.py new file mode 100644 index 00000000..aafab33b --- /dev/null +++ b/FreeTAKServer/model/SpecificCoT/SendOther.py @@ -0,0 +1,13 @@ +from .SpecificCoTAbstract import SpecificCoTAbstract + +class SendOther(SpecificCoTAbstract): + def __init__(self): + self.define_variables() + self.setType("other") + self.martiPresent = False + + def setMartiPresent(self, martiPresent): + self.martiPresent = martiPresent + + def getMartiPresent(self): + return self.martiPresent \ No newline at end of file diff --git a/FreeTAKServer/model/SpecificCoT/SendPing.py b/FreeTAKServer/model/SpecificCoT/SendPing.py new file mode 100644 index 00000000..accde470 --- /dev/null +++ b/FreeTAKServer/model/SpecificCoT/SendPing.py @@ -0,0 +1,6 @@ +from .SpecificCoTAbstract import SpecificCoTAbstract + +class SendPing(SpecificCoTAbstract): + def __init__(self): + self.define_variables() + self.setType("ping") diff --git a/FreeTAKServer/model/SpecificCoT/SendTakPong.py b/FreeTAKServer/model/SpecificCoT/SendTakPong.py new file mode 100644 index 00000000..99b2b991 --- /dev/null +++ b/FreeTAKServer/model/SpecificCoT/SendTakPong.py @@ -0,0 +1,7 @@ +from .SpecificCoTAbstract import SpecificCoTAbstract + +class SendTakPong(SpecificCoTAbstract): + def __init__(self): + self.define_variables() + self.setType("TakPong") + diff --git a/FreeTAKServer/model/SpecificCoT/SendUserUpdate.py b/FreeTAKServer/model/SpecificCoT/SendUserUpdate.py new file mode 100644 index 00000000..1092207a --- /dev/null +++ b/FreeTAKServer/model/SpecificCoT/SendUserUpdate.py @@ -0,0 +1,6 @@ +from .SpecificCoTAbstract import SpecificCoTAbstract + +class SendUserUpdate(SpecificCoTAbstract): + def __init__(self): + self.define_variables() + self.setType("UserUpdate") diff --git a/FreeTAKServer/model/SpecificCoT/SpecificCoTAbstract.py b/FreeTAKServer/model/SpecificCoT/SpecificCoTAbstract.py new file mode 100644 index 00000000..5b47f966 --- /dev/null +++ b/FreeTAKServer/model/SpecificCoT/SpecificCoTAbstract.py @@ -0,0 +1,30 @@ +class SpecificCoTAbstract: + def define_variables(self): + self.type = None + self.clientInformation = None + self.modelObject = None + self.xmlString = None + + def setType(self, type): + self.type = type + + def getType(self): + return self.type + + def setXmlString(self, xmlString): + self.xmlString = xmlString + + def getXmlString(self): + return self.xmlString + + def setClientInformation(self, clientInformation): + self.clientInformation = clientInformation + + def getClientInformation(self): + return self.clientInformation + + def setModelObject(self, modelObject): + self.modelObject = modelObject + + def getModelObject(self): + return self.modelObject diff --git a/FreeTAKServer/model/SpecificCoT/__init__.py b/FreeTAKServer/model/SpecificCoT/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/model/__init__.py b/FreeTAKServer/model/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/model/detailObject.py b/FreeTAKServer/model/detailObject.py new file mode 100644 index 00000000..53873862 --- /dev/null +++ b/FreeTAKServer/model/detailObject.py @@ -0,0 +1,3 @@ +class detailObject: + def __init__(self): + pass \ No newline at end of file diff --git a/FreeTAKServer/model/proto/contact.proto b/FreeTAKServer/model/proto/contact.proto new file mode 100644 index 00000000..d56977d9 --- /dev/null +++ b/FreeTAKServer/model/proto/contact.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +// All items are required unless otherwise noted! +// "required" means if they are missing on send, the conversion +// to the message format will be rejected and fall back to opaque +// XML representation +message Contact { + string endpoint = 1; // endpoint= + string callsign = 2; // callsign= +} diff --git a/FreeTAKServer/model/proto/cotevent.proto b/FreeTAKServer/model/proto/cotevent.proto new file mode 100644 index 00000000..664405bd --- /dev/null +++ b/FreeTAKServer/model/proto/cotevent.proto @@ -0,0 +1,40 @@ +syntax = "proto3"; + +import "detail.proto"; +// this seems to be used for all CoT sent from ATAK +// A note about timestamps: +// Uses "timeMs" units, which is number of milliseconds since +// 1970-01-01 00:00:00 UTC +// +// All items are required unless otherwise noted! +// "required" means if they are missing in the XML during outbound +// conversion to protobuf, the message will be +// rejected +message CotEvent { + // + + string type = 1; // + + string access = 2; // optional + string qos = 3; // optional + string opex = 4; // optional + + string uid = 5; // + uint64 sendTime = 6; // converted to timeMs + uint64 startTime = 7; // converted to timeMs + uint64 staleTime = 8; // converted to timeMs + string how = 9; // + + // + double lat = 10; // + double lon = 11; // + double hae = 12; // use 999999 for unknown + double ce = 13; // use 999999 for unknown + double le = 14; // use 999999 for unknown + + // comprises children of + // This is optional - if omitted, then the cot message + // had no data under + Detail detail = 15; +} + diff --git a/FreeTAKServer/model/proto/detail.proto b/FreeTAKServer/model/proto/detail.proto new file mode 100644 index 00000000..1c645c4c --- /dev/null +++ b/FreeTAKServer/model/proto/detail.proto @@ -0,0 +1,70 @@ +syntax = "proto3"; + +import "contact.proto"; +import "group.proto"; +import "precisionlocation.proto"; +import "status.proto"; +import "takv.proto"; +import "track.proto"; + +// CotEvent detail +// The strong typed message fields are optional. If used, they *MUST* adhere +// to the requirements of the message (see their proto file) and +// their XML source element used to populate the message MUST +// be omitted from the xmlDetail. +// WHOLE ELEMENTS MUST BE CONVERTED TO MESSAGES. Do not try to +// put part of the data from a given element into one of the messages +// and put other parts of the data in an element of xmlDetail! This applies +// especially if you add new things to the XML representation which do not +// have a place in the equivalent protobuf message. Instead, omit the +// message and put the entire element in xmlDetail! +// +// xmlDetail is optional. If omitted, all Detail data has been +// converted to the strongly typed message fields. +// If present, this contains any remaining detail data that has NOT been +// included in one of the strongly typed message fields. To process the +// xmlDetail, the following rules MUST be followed: +// Senders of this message MUST: +// 1. Remove all child elements used to populate the other message +// fields +// 2. If no child elements under remain, STOP - do not populate +// xmlDetail +// 3. Serialize the remaining XML tree under .... +// as XML in UTF-8 encoding +// 4. Remove the and element tags +// 5. Remove the XML header +// Receivers of this message MUST do the equivalent of the following: +// 1. If the field is not present (zero length), stop - do nothing +// 2. Prepend and append +// 3. Prepend an XML header for UTF-8 encoding, version 1.0 +// ( or similar) +// 4. Read the result, expecting a valid XML document with a document +// root of +// 5. Merge in XML equivalents of each of the strongly typed +// messages present in this Detail message. +// In the event that a sending application does not follow +// sending rule #1 above properly and data for the same element +// appears in xmlDetail, the data in xmlDetail should be left alone +// and the data in the equivalent message should ignored. + +message Detail { + string xmlDetail = 1; + + // + Contact contact = 2; + + // <__group> + Group group = 3; + + // + PrecisionLocation precisionLocation = 4; + + // + Status status = 5; + + // + Takv takv = 6; + + // + Track track = 7; +} diff --git a/FreeTAKServer/model/proto/fig.proto b/FreeTAKServer/model/proto/fig.proto new file mode 100644 index 00000000..b211f4d4 --- /dev/null +++ b/FreeTAKServer/model/proto/fig.proto @@ -0,0 +1,106 @@ +syntax = "proto3"; + +option objc_class_prefix = "TAK"; + +service FederatedChannel { + rpc SendOneEvent(FederatedEvent) returns (Empty) {} + rpc BinaryMessageStream(stream BinaryBlob) returns (Empty) {} + rpc SendOneBlob(BinaryBlob) returns (Empty) {} + rpc getIdentity(Empty) returns (Identity) {} + rpc ClientEventStream(Subscription) returns (stream FederatedEvent) {} + rpc ServerEventStream(stream FederatedEvent) returns (Subscription) {} + rpc HealthCheck(ClientHealth) returns (ServerHealth) {} + + rpc ClientROLStream(Subscription) returns (stream ROL) {} + rpc ServerROLStream(stream ROL) returns (Subscription) {} +} + +enum CRUD { INVALID = 0; CREATE = 1; READ = 2; UPDATE = 3; DELETE = 4; } +enum BINARY_TYPES { EMPTY = 0; OTHER = 1; IMAGE = 2; } + +message FederatedEvent { + GeoEvent event = 1; + ContactListEntry contact = 2; + repeated string federateGroups = 3; +} + +message GeoEvent { + int64 sendTime = 1; + int64 startTime = 2; + int64 staleTime = 3; + double lat = 4; // WSG-84 + double lon = 5; // WSG-84 + double hae = 6; // meters + double ce = 7; // meters + double le = 8; // meters + string uid = 9; // track-id + string type= 10; // CoT type + string coordSource = 11; // CoT 'how' + string other = 12; // CoT detail + int32 battery = 13; + string ploc = 14; + string palt = 15; + string screenName = 16; // callsign + string groupName = 17; + string groupRole = 18; + string phone = 19; + double speed = 20; + double course = 21; + BinaryBlob binary = 22; //image + repeated string ptpUids = 23; + repeated string ptpCallsigns = 24; // ugh...shouldn't need this +} + +message BinaryBlob { + BINARY_TYPES type = 1; + bytes data = 2; + string filename = 3; + int64 timestamp = 4; + string description = 5; +} + +message ContactListEntry { + CRUD operation = 1; + string uid = 2; + string callsign = 3; + string phone = 4; + string sip = 5; + string directConnect = 6; +} + +message Empty { } + +message Identity { + string name = 1; + string uid = 2; + string description = 3; +} + +message Subscription { + Identity identity = 1; + string filter = 2; +} + +message ClientHealth { + enum ServingStatus { + UNKNOWN = 0; + SERVING = 1; + NOT_SERVING = 2; + } + ServingStatus status = 1; +} + +message ServerHealth { + enum ServingStatus { + UNKNOWN = 0; + SERVING = 1; + NOT_SERVING = 2; + NOT_CONNECTED = 3; + } + ServingStatus status = 1; +} + +message ROL { + string program = 1; + repeated BinaryBlob payload = 2; +} diff --git a/FreeTAKServer/model/proto/group.proto b/FreeTAKServer/model/proto/group.proto new file mode 100644 index 00000000..47067985 --- /dev/null +++ b/FreeTAKServer/model/proto/group.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; +//difference + +// All items are required unless otherwise noted! +// "required" means if they are missing on send, the conversion +// to the message format will be rejected and fall back to opaque +// XML representation +message Group { + string name = 1; // name= + string role = 2; // role= +} diff --git a/FreeTAKServer/model/proto/precisionlocation.proto b/FreeTAKServer/model/proto/precisionlocation.proto new file mode 100644 index 00000000..be7af603 --- /dev/null +++ b/FreeTAKServer/model/proto/precisionlocation.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +// All items are required unless otherwise noted! +// "required" means if they are missing on send, the conversion +// to the message format will be rejected and fall back to opaque +// XML representation +message PrecisionLocation { + string geopointsrc = 1; // geopointsrc= + string altsrc = 2; // altsrc= +} diff --git a/FreeTAKServer/model/proto/simple.proto b/FreeTAKServer/model/proto/simple.proto new file mode 100644 index 00000000..ca2987cc --- /dev/null +++ b/FreeTAKServer/model/proto/simple.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +// All items are required unless otherwise noted! +// "required" means if they are missing on send, the conversion +// to the message format will be rejected and fall back to opaque +// XML representation +message Simple { + string endpoint = 1; // endpoint= + string callsign = 2; // callsign= +} \ No newline at end of file diff --git a/FreeTAKServer/model/proto/status.proto b/FreeTAKServer/model/proto/status.proto new file mode 100644 index 00000000..616fb4bd --- /dev/null +++ b/FreeTAKServer/model/proto/status.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +// All items are required unless otherwise noted! +// "required" means if they are missing on send, the conversion +// to the message format will be rejected and fall back to opaque +// XML representation +message Status { + uint32 battery = 1; // battery= +} diff --git a/FreeTAKServer/model/proto/takcontrol.proto b/FreeTAKServer/model/proto/takcontrol.proto new file mode 100644 index 00000000..56c89fce --- /dev/null +++ b/FreeTAKServer/model/proto/takcontrol.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +// TAK Protocol control message +// This specifies to a recipient what versions +// of protocol elements this sender supports during +// decoding. +message TakControl { + // Lowest TAK protocol version supported + // If not filled in (reads as 0), version 1 is assumed + uint32 minProtoVersion = 1; + + // Highest TAK protocol version supported + // If not filled in (reads as 0), version 1 is assumed + uint32 maxProtoVersion = 2; +} + diff --git a/FreeTAKServer/model/proto/takmessage.proto b/FreeTAKServer/model/proto/takmessage.proto new file mode 100644 index 00000000..10e7bfd9 --- /dev/null +++ b/FreeTAKServer/model/proto/takmessage.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +import "cotevent.proto"; +import "takcontrol.proto"; + +// Top level message sent for TAK Messaging Protocol Version 1. +message TakMessage { + // Optional - if omitted, continue using last reported control + // information + TakControl takControl = 1; + + // Optional - if omitted, no event data in this message + CotEvent cotEvent = 2; +} + diff --git a/FreeTAKServer/model/proto/takv.proto b/FreeTAKServer/model/proto/takv.proto new file mode 100644 index 00000000..67a0dc84 --- /dev/null +++ b/FreeTAKServer/model/proto/takv.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +// All items are required unless otherwise noted! +// "required" means if they are missing on send, the conversion +// to the message format will be rejected and fall back to opaque +// XML representation +message Takv { + string device = 1; // device= + string platform = 2; // platform= + string os = 3; // os= + string version = 4; // version= +} diff --git a/FreeTAKServer/model/proto/track.proto b/FreeTAKServer/model/proto/track.proto new file mode 100644 index 00000000..570232b1 --- /dev/null +++ b/FreeTAKServer/model/proto/track.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +// All items are required unless otherwise noted! +// "required" means if they are missing on send, the conversion +// to the message format will be rejected and fall back to opaque +// XML representation +message Track { + double speed = 1; // speed= + double course = 2; // course= +} diff --git a/FreeTAKServer/model/protobuf/__init__.py b/FreeTAKServer/model/protobuf/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/model/protobuf/contact.proto b/FreeTAKServer/model/protobuf/contact.proto new file mode 100644 index 00000000..d56977d9 --- /dev/null +++ b/FreeTAKServer/model/protobuf/contact.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +// All items are required unless otherwise noted! +// "required" means if they are missing on send, the conversion +// to the message format will be rejected and fall back to opaque +// XML representation +message Contact { + string endpoint = 1; // endpoint= + string callsign = 2; // callsign= +} diff --git a/FreeTAKServer/model/protobuf/cotevent.proto b/FreeTAKServer/model/protobuf/cotevent.proto new file mode 100644 index 00000000..664405bd --- /dev/null +++ b/FreeTAKServer/model/protobuf/cotevent.proto @@ -0,0 +1,40 @@ +syntax = "proto3"; + +import "detail.proto"; +// this seems to be used for all CoT sent from ATAK +// A note about timestamps: +// Uses "timeMs" units, which is number of milliseconds since +// 1970-01-01 00:00:00 UTC +// +// All items are required unless otherwise noted! +// "required" means if they are missing in the XML during outbound +// conversion to protobuf, the message will be +// rejected +message CotEvent { + // + + string type = 1; // + + string access = 2; // optional + string qos = 3; // optional + string opex = 4; // optional + + string uid = 5; // + uint64 sendTime = 6; // converted to timeMs + uint64 startTime = 7; // converted to timeMs + uint64 staleTime = 8; // converted to timeMs + string how = 9; // + + // + double lat = 10; // + double lon = 11; // + double hae = 12; // use 999999 for unknown + double ce = 13; // use 999999 for unknown + double le = 14; // use 999999 for unknown + + // comprises children of + // This is optional - if omitted, then the cot message + // had no data under + Detail detail = 15; +} + diff --git a/FreeTAKServer/model/protobuf/detail.proto b/FreeTAKServer/model/protobuf/detail.proto new file mode 100644 index 00000000..1c645c4c --- /dev/null +++ b/FreeTAKServer/model/protobuf/detail.proto @@ -0,0 +1,70 @@ +syntax = "proto3"; + +import "contact.proto"; +import "group.proto"; +import "precisionlocation.proto"; +import "status.proto"; +import "takv.proto"; +import "track.proto"; + +// CotEvent detail +// The strong typed message fields are optional. If used, they *MUST* adhere +// to the requirements of the message (see their proto file) and +// their XML source element used to populate the message MUST +// be omitted from the xmlDetail. +// WHOLE ELEMENTS MUST BE CONVERTED TO MESSAGES. Do not try to +// put part of the data from a given element into one of the messages +// and put other parts of the data in an element of xmlDetail! This applies +// especially if you add new things to the XML representation which do not +// have a place in the equivalent protobuf message. Instead, omit the +// message and put the entire element in xmlDetail! +// +// xmlDetail is optional. If omitted, all Detail data has been +// converted to the strongly typed message fields. +// If present, this contains any remaining detail data that has NOT been +// included in one of the strongly typed message fields. To process the +// xmlDetail, the following rules MUST be followed: +// Senders of this message MUST: +// 1. Remove all child elements used to populate the other message +// fields +// 2. If no child elements under remain, STOP - do not populate +// xmlDetail +// 3. Serialize the remaining XML tree under .... +// as XML in UTF-8 encoding +// 4. Remove the and element tags +// 5. Remove the XML header +// Receivers of this message MUST do the equivalent of the following: +// 1. If the field is not present (zero length), stop - do nothing +// 2. Prepend and append +// 3. Prepend an XML header for UTF-8 encoding, version 1.0 +// ( or similar) +// 4. Read the result, expecting a valid XML document with a document +// root of +// 5. Merge in XML equivalents of each of the strongly typed +// messages present in this Detail message. +// In the event that a sending application does not follow +// sending rule #1 above properly and data for the same element +// appears in xmlDetail, the data in xmlDetail should be left alone +// and the data in the equivalent message should ignored. + +message Detail { + string xmlDetail = 1; + + // + Contact contact = 2; + + // <__group> + Group group = 3; + + // + PrecisionLocation precisionLocation = 4; + + // + Status status = 5; + + // + Takv takv = 6; + + // + Track track = 7; +} diff --git a/FreeTAKServer/model/protobuf/fig.proto b/FreeTAKServer/model/protobuf/fig.proto new file mode 100644 index 00000000..09da52e2 --- /dev/null +++ b/FreeTAKServer/model/protobuf/fig.proto @@ -0,0 +1,106 @@ +syntax = "proto3"; + +option objc_class_prefix = "TAK"; + +service FederatedChannel { + rpc SendOneEvent(FederatedEvent) returns (Empty) {} + rpc BinaryMessageStream(stream BinaryBlob) returns (Empty) {} + rpc SendOneBlob(BinaryBlob) returns (Empty) {} + rpc getIdentity(Empty) returns (Identity) {} + rpc ClientEventStream(Subscription) returns (stream FederatedEvent) {} + rpc ServerEventStream(stream FederatedEvent) returns (Subscription) {} + rpc HealthCheck(ClientHealth) returns (ServerHealth) {} + + rpc ClientROLStream(Subscription) returns (stream ROL) {} + rpc ServerROLStream(stream ROL) returns (Subscription) {} +} + +enum CRUD { INVALID = 0; CREATE = 1; READ = 2; UPDATE = 3; DELETE = 4; } +enum BINARY_TYPES { EMPTY = 0; OTHER = 1; IMAGE = 2; } + +message FederatedEvent { + GeoEvent event = 1; + ContactListEntry contact = 2; + repeated string windows = 3; +} + +message GeoEvent { + int64 sendTime = 1; + int64 startTime = 2; + int64 staleTime = 3; + double lat = 4; // WSG-84 + double lon = 5; // WSG-84 + double hae = 6; // meters + double ce = 7; // meters + double le = 8; // meters + string uid = 9; // track-id + string type= 10; // CoT type + string coordSource = 11; // CoT 'how' + string other = 12; // CoT detail + int32 battery = 13; + string ploc = 14; + string palt = 15; + string screenName = 16; // callsign + string groupName = 17; + string groupRole = 18; + string phone = 19; + double speed = 20; + double course = 21; + BinaryBlob binary = 22; //image + repeated string ptpUids = 23; + repeated string ptpCallsigns = 24; // ugh...shouldn't need this +} + +message BinaryBlob { + BINARY_TYPES type = 1; + bytes data = 2; + string filename = 3; + int64 timestamp = 4; + string description = 5; +} + +message ContactListEntry { + CRUD operation = 1; + string uid = 2; + string callsign = 3; + string phone = 4; + string sip = 5; + string directConnect = 6; +} + +message Empty { } + +message Identity { + string name = 1; + string uid = 2; + string description = 3; +} + +message Subscription { + Identity identity = 1; + string filter = 2; +} + +message ClientHealth { + enum ServingStatus { + UNKNOWN = 0; + SERVING = 1; + NOT_SERVING = 2; + } + ServingStatus status = 1; +} + +message ServerHealth { + enum ServingStatus { + UNKNOWN = 0; + SERVING = 1; + NOT_SERVING = 2; + NOT_CONNECTED = 3; + } + ServingStatus status = 1; +} + +message ROL { + string program = 1; + repeated BinaryBlob payload = 2; +} diff --git a/FreeTAKServer/model/protobuf/group.proto b/FreeTAKServer/model/protobuf/group.proto new file mode 100644 index 00000000..47067985 --- /dev/null +++ b/FreeTAKServer/model/protobuf/group.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; +//difference + +// All items are required unless otherwise noted! +// "required" means if they are missing on send, the conversion +// to the message format will be rejected and fall back to opaque +// XML representation +message Group { + string name = 1; // name= + string role = 2; // role= +} diff --git a/FreeTAKServer/model/protobuf/precisionlocation.proto b/FreeTAKServer/model/protobuf/precisionlocation.proto new file mode 100644 index 00000000..be7af603 --- /dev/null +++ b/FreeTAKServer/model/protobuf/precisionlocation.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +// All items are required unless otherwise noted! +// "required" means if they are missing on send, the conversion +// to the message format will be rejected and fall back to opaque +// XML representation +message PrecisionLocation { + string geopointsrc = 1; // geopointsrc= + string altsrc = 2; // altsrc= +} diff --git a/FreeTAKServer/model/protobuf/simple.proto b/FreeTAKServer/model/protobuf/simple.proto new file mode 100644 index 00000000..ca2987cc --- /dev/null +++ b/FreeTAKServer/model/protobuf/simple.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +// All items are required unless otherwise noted! +// "required" means if they are missing on send, the conversion +// to the message format will be rejected and fall back to opaque +// XML representation +message Simple { + string endpoint = 1; // endpoint= + string callsign = 2; // callsign= +} \ No newline at end of file diff --git a/FreeTAKServer/model/protobuf/status.proto b/FreeTAKServer/model/protobuf/status.proto new file mode 100644 index 00000000..616fb4bd --- /dev/null +++ b/FreeTAKServer/model/protobuf/status.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +// All items are required unless otherwise noted! +// "required" means if they are missing on send, the conversion +// to the message format will be rejected and fall back to opaque +// XML representation +message Status { + uint32 battery = 1; // battery= +} diff --git a/FreeTAKServer/model/protobuf/takcontrol.proto b/FreeTAKServer/model/protobuf/takcontrol.proto new file mode 100644 index 00000000..56c89fce --- /dev/null +++ b/FreeTAKServer/model/protobuf/takcontrol.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +// TAK Protocol control message +// This specifies to a recipient what versions +// of protocol elements this sender supports during +// decoding. +message TakControl { + // Lowest TAK protocol version supported + // If not filled in (reads as 0), version 1 is assumed + uint32 minProtoVersion = 1; + + // Highest TAK protocol version supported + // If not filled in (reads as 0), version 1 is assumed + uint32 maxProtoVersion = 2; +} + diff --git a/FreeTAKServer/model/protobuf/takmessage.proto b/FreeTAKServer/model/protobuf/takmessage.proto new file mode 100644 index 00000000..10e7bfd9 --- /dev/null +++ b/FreeTAKServer/model/protobuf/takmessage.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +import "cotevent.proto"; +import "takcontrol.proto"; + +// Top level message sent for TAK Messaging Protocol Version 1. +message TakMessage { + // Optional - if omitted, continue using last reported control + // information + TakControl takControl = 1; + + // Optional - if omitted, no event data in this message + CotEvent cotEvent = 2; +} + diff --git a/FreeTAKServer/model/protobuf/takv.proto b/FreeTAKServer/model/protobuf/takv.proto new file mode 100644 index 00000000..67a0dc84 --- /dev/null +++ b/FreeTAKServer/model/protobuf/takv.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +// All items are required unless otherwise noted! +// "required" means if they are missing on send, the conversion +// to the message format will be rejected and fall back to opaque +// XML representation +message Takv { + string device = 1; // device= + string platform = 2; // platform= + string os = 3; // os= + string version = 4; // version= +} diff --git a/FreeTAKServer/model/protobuf/track.proto b/FreeTAKServer/model/protobuf/track.proto new file mode 100644 index 00000000..570232b1 --- /dev/null +++ b/FreeTAKServer/model/protobuf/track.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +// All items are required unless otherwise noted! +// "required" means if they are missing on send, the conversion +// to the message format will be rejected and fall back to opaque +// XML representation +message Track { + double speed = 1; // speed= + double course = 2; // course= +} diff --git a/FreeTAKServer/model/protobufModel/__init__.py b/FreeTAKServer/model/protobufModel/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/model/protobufModel/contact_pb2.py b/FreeTAKServer/model/protobufModel/contact_pb2.py new file mode 100644 index 00000000..85eddd1f --- /dev/null +++ b/FreeTAKServer/model/protobufModel/contact_pb2.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: contact.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='contact.proto', + package='', + syntax='proto3', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\rcontact.proto\"-\n\x07\x43ontact\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x10\n\x08\x63\x61llsign\x18\x02 \x01(\tb\x06proto3' +) + + + + +_CONTACT = _descriptor.Descriptor( + name='Contact', + full_name='Contact', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='endpoint', full_name='Contact.endpoint', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='callsign', full_name='Contact.callsign', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=17, + serialized_end=62, +) + +DESCRIPTOR.message_types_by_name['Contact'] = _CONTACT +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Contact = _reflection.GeneratedProtocolMessageType('Contact', (_message.Message,), { + 'DESCRIPTOR' : _CONTACT, + '__module__' : 'contact_pb2' + # @@protoc_insertion_point(class_scope:Contact) + }) +_sym_db.RegisterMessage(Contact) + + +# @@protoc_insertion_point(module_scope) diff --git a/FreeTAKServer/model/protobufModel/cotevent_pb2.py b/FreeTAKServer/model/protobufModel/cotevent_pb2.py new file mode 100644 index 00000000..aa63296d --- /dev/null +++ b/FreeTAKServer/model/protobufModel/cotevent_pb2.py @@ -0,0 +1,171 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: cotevent.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import detail_pb2 as detail__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='cotevent.proto', + package='', + syntax='proto3', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x0e\x63otevent.proto\x1a\x0c\x64\x65tail.proto\"\xed\x01\n\x08\x43otEvent\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0e\n\x06\x61\x63\x63\x65ss\x18\x02 \x01(\t\x12\x0b\n\x03qos\x18\x03 \x01(\t\x12\x0c\n\x04opex\x18\x04 \x01(\t\x12\x0b\n\x03uid\x18\x05 \x01(\t\x12\x10\n\x08sendTime\x18\x06 \x01(\x04\x12\x11\n\tstartTime\x18\x07 \x01(\x04\x12\x11\n\tstaleTime\x18\x08 \x01(\x04\x12\x0b\n\x03how\x18\t \x01(\t\x12\x0b\n\x03lat\x18\n \x01(\x01\x12\x0b\n\x03lon\x18\x0b \x01(\x01\x12\x0b\n\x03hae\x18\x0c \x01(\x01\x12\n\n\x02\x63\x65\x18\r \x01(\x01\x12\n\n\x02le\x18\x0e \x01(\x01\x12\x17\n\x06\x64\x65tail\x18\x0f \x01(\x0b\x32\x07.Detailb\x06proto3' + , + dependencies=[detail__pb2.DESCRIPTOR,]) + + + + +_COTEVENT = _descriptor.Descriptor( + name='CotEvent', + full_name='CotEvent', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='type', full_name='CotEvent.type', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='access', full_name='CotEvent.access', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='qos', full_name='CotEvent.qos', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='opex', full_name='CotEvent.opex', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uid', full_name='CotEvent.uid', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='sendTime', full_name='CotEvent.sendTime', index=5, + number=6, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='startTime', full_name='CotEvent.startTime', index=6, + number=7, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='staleTime', full_name='CotEvent.staleTime', index=7, + number=8, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='how', full_name='CotEvent.how', index=8, + number=9, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='lat', full_name='CotEvent.lat', index=9, + number=10, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='lon', full_name='CotEvent.lon', index=10, + number=11, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='hae', full_name='CotEvent.hae', index=11, + number=12, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='ce', full_name='CotEvent.ce', index=12, + number=13, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='le', full_name='CotEvent.le', index=13, + number=14, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='detail', full_name='CotEvent.detail', index=14, + number=15, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=33, + serialized_end=270, +) + +_COTEVENT.fields_by_name['detail'].message_type = detail__pb2._DETAIL +DESCRIPTOR.message_types_by_name['CotEvent'] = _COTEVENT +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +CotEvent = _reflection.GeneratedProtocolMessageType('CotEvent', (_message.Message,), { + 'DESCRIPTOR' : _COTEVENT, + '__module__' : 'cotevent_pb2' + # @@protoc_insertion_point(class_scope:CotEvent) + }) +_sym_db.RegisterMessage(CotEvent) + + +# @@protoc_insertion_point(module_scope) diff --git a/FreeTAKServer/model/protobufModel/detail_pb2.py b/FreeTAKServer/model/protobufModel/detail_pb2.py new file mode 100644 index 00000000..564578e1 --- /dev/null +++ b/FreeTAKServer/model/protobufModel/detail_pb2.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: detail.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import contact_pb2 as contact__pb2 +import group_pb2 as group__pb2 +import precisionlocation_pb2 as precisionlocation__pb2 +import status_pb2 as status__pb2 +import takv_pb2 as takv__pb2 +import track_pb2 as track__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='detail.proto', + package='', + syntax='proto3', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x0c\x64\x65tail.proto\x1a\rcontact.proto\x1a\x0bgroup.proto\x1a\x17precisionlocation.proto\x1a\x0cstatus.proto\x1a\ntakv.proto\x1a\x0btrack.proto\"\xc1\x01\n\x06\x44\x65tail\x12\x11\n\txmlDetail\x18\x01 \x01(\t\x12\x19\n\x07\x63ontact\x18\x02 \x01(\x0b\x32\x08.Contact\x12\x15\n\x05group\x18\x03 \x01(\x0b\x32\x06.Group\x12-\n\x11precisionLocation\x18\x04 \x01(\x0b\x32\x12.PrecisionLocation\x12\x17\n\x06status\x18\x05 \x01(\x0b\x32\x07.Status\x12\x13\n\x04takv\x18\x06 \x01(\x0b\x32\x05.Takv\x12\x15\n\x05track\x18\x07 \x01(\x0b\x32\x06.Trackb\x06proto3' + , + dependencies=[contact__pb2.DESCRIPTOR,group__pb2.DESCRIPTOR,precisionlocation__pb2.DESCRIPTOR,status__pb2.DESCRIPTOR,takv__pb2.DESCRIPTOR,track__pb2.DESCRIPTOR,]) + + + + +_DETAIL = _descriptor.Descriptor( + name='Detail', + full_name='Detail', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='xmlDetail', full_name='Detail.xmlDetail', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='contact', full_name='Detail.contact', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='group', full_name='Detail.group', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='precisionLocation', full_name='Detail.precisionLocation', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='status', full_name='Detail.status', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='takv', full_name='Detail.takv', index=5, + number=6, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='track', full_name='Detail.track', index=6, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=109, + serialized_end=302, +) + +_DETAIL.fields_by_name['contact'].message_type = contact__pb2._CONTACT +_DETAIL.fields_by_name['group'].message_type = group__pb2._GROUP +_DETAIL.fields_by_name['precisionLocation'].message_type = precisionlocation__pb2._PRECISIONLOCATION +_DETAIL.fields_by_name['status'].message_type = status__pb2._STATUS +_DETAIL.fields_by_name['takv'].message_type = takv__pb2._TAKV +_DETAIL.fields_by_name['track'].message_type = track__pb2._TRACK +DESCRIPTOR.message_types_by_name['Detail'] = _DETAIL +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Detail = _reflection.GeneratedProtocolMessageType('Detail', (_message.Message,), { + 'DESCRIPTOR' : _DETAIL, + '__module__' : 'detail_pb2' + # @@protoc_insertion_point(class_scope:Detail) + }) +_sym_db.RegisterMessage(Detail) + + +# @@protoc_insertion_point(module_scope) diff --git a/FreeTAKServer/model/protobufModel/fig_pb2.py b/FreeTAKServer/model/protobufModel/fig_pb2.py new file mode 100644 index 00000000..9228507f --- /dev/null +++ b/FreeTAKServer/model/protobufModel/fig_pb2.py @@ -0,0 +1,957 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: fig.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='fig.proto', + package='com.atakmap', + syntax='proto3', + serialized_options=b'\242\002\003TAK', + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\tfig.proto\x12\x0b\x63om.atakmap\"~\n\x0e\x46\x65\x64\x65ratedEvent\x12$\n\x05\x65vent\x18\x01 \x01(\x0b\x32\x15.com.atakmap.GeoEvent\x12.\n\x07\x63ontact\x18\x02 \x01(\x0b\x32\x1d.com.atakmap.ContactListEntry\x12\x16\n\x0e\x66\x65\x64\x65rateGroups\x18\x03 \x03(\t\"\xa5\x03\n\x08GeoEvent\x12\x10\n\x08sendTime\x18\x01 \x01(\x03\x12\x11\n\tstartTime\x18\x02 \x01(\x03\x12\x11\n\tstaleTime\x18\x03 \x01(\x03\x12\x0b\n\x03lat\x18\x04 \x01(\x01\x12\x0b\n\x03lon\x18\x05 \x01(\x01\x12\x0b\n\x03hae\x18\x06 \x01(\x01\x12\n\n\x02\x63\x65\x18\x07 \x01(\x01\x12\n\n\x02le\x18\x08 \x01(\x01\x12\x0b\n\x03uid\x18\t \x01(\t\x12\x0c\n\x04type\x18\n \x01(\t\x12\x13\n\x0b\x63oordSource\x18\x0b \x01(\t\x12\r\n\x05other\x18\x0c \x01(\t\x12\x0f\n\x07\x62\x61ttery\x18\r \x01(\x05\x12\x0c\n\x04ploc\x18\x0e \x01(\t\x12\x0c\n\x04palt\x18\x0f \x01(\t\x12\x12\n\nscreenName\x18\x10 \x01(\t\x12\x11\n\tgroupName\x18\x11 \x01(\t\x12\x11\n\tgroupRole\x18\x12 \x01(\t\x12\r\n\x05phone\x18\x13 \x01(\t\x12\r\n\x05speed\x18\x14 \x01(\x01\x12\x0e\n\x06\x63ourse\x18\x15 \x01(\x01\x12\'\n\x06\x62inary\x18\x16 \x01(\x0b\x32\x17.com.atakmap.BinaryBlob\x12\x0f\n\x07ptpUids\x18\x17 \x03(\t\x12\x14\n\x0cptpCallsigns\x18\x18 \x03(\t\"}\n\nBinaryBlob\x12\'\n\x04type\x18\x01 \x01(\x0e\x32\x19.com.atakmap.BINARY_TYPES\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12\x10\n\x08\x66ilename\x18\x03 \x01(\t\x12\x11\n\ttimestamp\x18\x04 \x01(\x03\x12\x13\n\x0b\x64\x65scription\x18\x05 \x01(\t\"\x8a\x01\n\x10\x43ontactListEntry\x12$\n\toperation\x18\x01 \x01(\x0e\x32\x11.com.atakmap.CRUD\x12\x0b\n\x03uid\x18\x02 \x01(\t\x12\x10\n\x08\x63\x61llsign\x18\x03 \x01(\t\x12\r\n\x05phone\x18\x04 \x01(\t\x12\x0b\n\x03sip\x18\x05 \x01(\t\x12\x15\n\rdirectConnect\x18\x06 \x01(\t\"\x07\n\x05\x45mpty\":\n\x08Identity\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0b\n\x03uid\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\"G\n\x0cSubscription\x12\'\n\x08identity\x18\x01 \x01(\x0b\x32\x15.com.atakmap.Identity\x12\x0e\n\x06\x66ilter\x18\x02 \x01(\t\"\x83\x01\n\x0c\x43lientHealth\x12\x37\n\x06status\x18\x01 \x01(\x0e\x32\'.com.atakmap.ClientHealth.ServingStatus\":\n\rServingStatus\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0b\n\x07SERVING\x10\x01\x12\x0f\n\x0bNOT_SERVING\x10\x02\"\x96\x01\n\x0cServerHealth\x12\x37\n\x06status\x18\x01 \x01(\x0e\x32\'.com.atakmap.ServerHealth.ServingStatus\"M\n\rServingStatus\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0b\n\x07SERVING\x10\x01\x12\x0f\n\x0bNOT_SERVING\x10\x02\x12\x11\n\rNOT_CONNECTED\x10\x03\"@\n\x03ROL\x12\x0f\n\x07program\x18\x01 \x01(\t\x12(\n\x07payload\x18\x02 \x03(\x0b\x32\x17.com.atakmap.BinaryBlob*A\n\x04\x43RUD\x12\x0b\n\x07INVALID\x10\x00\x12\n\n\x06\x43REATE\x10\x01\x12\x08\n\x04READ\x10\x02\x12\n\n\x06UPDATE\x10\x03\x12\n\n\x06\x44\x45LETE\x10\x04*/\n\x0c\x42INARY_TYPES\x12\t\n\x05\x45MPTY\x10\x00\x12\t\n\x05OTHER\x10\x01\x12\t\n\x05IMAGE\x10\x02\x32\x88\x05\n\x10\x46\x65\x64\x65ratedChannel\x12\x41\n\x0cSendOneEvent\x12\x1b.com.atakmap.FederatedEvent\x1a\x12.com.atakmap.Empty\"\x00\x12\x46\n\x13\x42inaryMessageStream\x12\x17.com.atakmap.BinaryBlob\x1a\x12.com.atakmap.Empty\"\x00(\x01\x12<\n\x0bSendOneBlob\x12\x17.com.atakmap.BinaryBlob\x1a\x12.com.atakmap.Empty\"\x00\x12:\n\x0bgetIdentity\x12\x12.com.atakmap.Empty\x1a\x15.com.atakmap.Identity\"\x00\x12O\n\x11\x43lientEventStream\x12\x19.com.atakmap.Subscription\x1a\x1b.com.atakmap.FederatedEvent\"\x00\x30\x01\x12O\n\x11ServerEventStream\x12\x1b.com.atakmap.FederatedEvent\x1a\x19.com.atakmap.Subscription\"\x00(\x01\x12\x45\n\x0bHealthCheck\x12\x19.com.atakmap.ClientHealth\x1a\x19.com.atakmap.ServerHealth\"\x00\x12\x42\n\x0f\x43lientROLStream\x12\x19.com.atakmap.Subscription\x1a\x10.com.atakmap.ROL\"\x00\x30\x01\x12\x42\n\x0fServerROLStream\x12\x10.com.atakmap.ROL\x1a\x19.com.atakmap.Subscription\"\x00(\x01\x42\x06\xa2\x02\x03TAKb\x06proto3' +) + +_CRUD = _descriptor.EnumDescriptor( + name='CRUD', + full_name='com.atakmap.CRUD', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='INVALID', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CREATE', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='READ', index=2, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='UPDATE', index=3, number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='DELETE', index=4, number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=1341, + serialized_end=1406, +) +_sym_db.RegisterEnumDescriptor(_CRUD) + +CRUD = enum_type_wrapper.EnumTypeWrapper(_CRUD) +_BINARY_TYPES = _descriptor.EnumDescriptor( + name='BINARY_TYPES', + full_name='com.atakmap.BINARY_TYPES', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='EMPTY', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OTHER', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='IMAGE', index=2, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=1408, + serialized_end=1455, +) +_sym_db.RegisterEnumDescriptor(_BINARY_TYPES) + +BINARY_TYPES = enum_type_wrapper.EnumTypeWrapper(_BINARY_TYPES) +INVALID = 0 +CREATE = 1 +READ = 2 +UPDATE = 3 +DELETE = 4 +EMPTY = 0 +OTHER = 1 +IMAGE = 2 + + +_CLIENTHEALTH_SERVINGSTATUS = _descriptor.EnumDescriptor( + name='ServingStatus', + full_name='com.atakmap.ClientHealth.ServingStatus', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SERVING', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='NOT_SERVING', index=2, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=1062, + serialized_end=1120, +) +_sym_db.RegisterEnumDescriptor(_CLIENTHEALTH_SERVINGSTATUS) + +_SERVERHEALTH_SERVINGSTATUS = _descriptor.EnumDescriptor( + name='ServingStatus', + full_name='com.atakmap.ServerHealth.ServingStatus', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SERVING', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='NOT_SERVING', index=2, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='NOT_CONNECTED', index=3, number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=1196, + serialized_end=1273, +) +_sym_db.RegisterEnumDescriptor(_SERVERHEALTH_SERVINGSTATUS) + + +_FEDERATEDEVENT = _descriptor.Descriptor( + name='FederatedEvent', + full_name='com.atakmap.FederatedEvent', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='event', full_name='com.atakmap.FederatedEvent.event', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='contact', full_name='com.atakmap.FederatedEvent.contact', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='federateGroups', full_name='com.atakmap.FederatedEvent.federateGroups', index=2, + number=3, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=26, + serialized_end=152, +) + + +_GEOEVENT = _descriptor.Descriptor( + name='GeoEvent', + full_name='com.atakmap.GeoEvent', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='sendTime', full_name='com.atakmap.GeoEvent.sendTime', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='startTime', full_name='com.atakmap.GeoEvent.startTime', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='staleTime', full_name='com.atakmap.GeoEvent.staleTime', index=2, + number=3, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='lat', full_name='com.atakmap.GeoEvent.lat', index=3, + number=4, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='lon', full_name='com.atakmap.GeoEvent.lon', index=4, + number=5, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='hae', full_name='com.atakmap.GeoEvent.hae', index=5, + number=6, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='ce', full_name='com.atakmap.GeoEvent.ce', index=6, + number=7, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='le', full_name='com.atakmap.GeoEvent.le', index=7, + number=8, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uid', full_name='com.atakmap.GeoEvent.uid', index=8, + number=9, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='type', full_name='com.atakmap.GeoEvent.type', index=9, + number=10, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='coordSource', full_name='com.atakmap.GeoEvent.coordSource', index=10, + number=11, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='other', full_name='com.atakmap.GeoEvent.other', index=11, + number=12, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='battery', full_name='com.atakmap.GeoEvent.battery', index=12, + number=13, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='ploc', full_name='com.atakmap.GeoEvent.ploc', index=13, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='palt', full_name='com.atakmap.GeoEvent.palt', index=14, + number=15, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='screenName', full_name='com.atakmap.GeoEvent.screenName', index=15, + number=16, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='groupName', full_name='com.atakmap.GeoEvent.groupName', index=16, + number=17, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='groupRole', full_name='com.atakmap.GeoEvent.groupRole', index=17, + number=18, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='phone', full_name='com.atakmap.GeoEvent.phone', index=18, + number=19, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='speed', full_name='com.atakmap.GeoEvent.speed', index=19, + number=20, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='course', full_name='com.atakmap.GeoEvent.course', index=20, + number=21, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='binary', full_name='com.atakmap.GeoEvent.binary', index=21, + number=22, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='ptpUids', full_name='com.atakmap.GeoEvent.ptpUids', index=22, + number=23, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='ptpCallsigns', full_name='com.atakmap.GeoEvent.ptpCallsigns', index=23, + number=24, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=155, + serialized_end=576, +) + + +_BINARYBLOB = _descriptor.Descriptor( + name='BinaryBlob', + full_name='com.atakmap.BinaryBlob', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='type', full_name='com.atakmap.BinaryBlob.type', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='data', full_name='com.atakmap.BinaryBlob.data', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='filename', full_name='com.atakmap.BinaryBlob.filename', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='timestamp', full_name='com.atakmap.BinaryBlob.timestamp', index=3, + number=4, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='description', full_name='com.atakmap.BinaryBlob.description', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=578, + serialized_end=703, +) + + +_CONTACTLISTENTRY = _descriptor.Descriptor( + name='ContactListEntry', + full_name='com.atakmap.ContactListEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='operation', full_name='com.atakmap.ContactListEntry.operation', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uid', full_name='com.atakmap.ContactListEntry.uid', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='callsign', full_name='com.atakmap.ContactListEntry.callsign', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='phone', full_name='com.atakmap.ContactListEntry.phone', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='sip', full_name='com.atakmap.ContactListEntry.sip', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='directConnect', full_name='com.atakmap.ContactListEntry.directConnect', index=5, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=706, + serialized_end=844, +) + + +_EMPTY = _descriptor.Descriptor( + name='Empty', + full_name='com.atakmap.Empty', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=846, + serialized_end=853, +) + + +_IDENTITY = _descriptor.Descriptor( + name='Identity', + full_name='com.atakmap.Identity', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='com.atakmap.Identity.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uid', full_name='com.atakmap.Identity.uid', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='description', full_name='com.atakmap.Identity.description', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=855, + serialized_end=913, +) + + +_SUBSCRIPTION = _descriptor.Descriptor( + name='Subscription', + full_name='com.atakmap.Subscription', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='identity', full_name='com.atakmap.Subscription.identity', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='filter', full_name='com.atakmap.Subscription.filter', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=915, + serialized_end=986, +) + + +_CLIENTHEALTH = _descriptor.Descriptor( + name='ClientHealth', + full_name='com.atakmap.ClientHealth', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='status', full_name='com.atakmap.ClientHealth.status', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _CLIENTHEALTH_SERVINGSTATUS, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=989, + serialized_end=1120, +) + + +_SERVERHEALTH = _descriptor.Descriptor( + name='ServerHealth', + full_name='com.atakmap.ServerHealth', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='status', full_name='com.atakmap.ServerHealth.status', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _SERVERHEALTH_SERVINGSTATUS, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1123, + serialized_end=1273, +) + + +_ROL = _descriptor.Descriptor( + name='ROL', + full_name='com.atakmap.ROL', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='program', full_name='com.atakmap.ROL.program', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='payload', full_name='com.atakmap.ROL.payload', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1275, + serialized_end=1339, +) + +_FEDERATEDEVENT.fields_by_name['event'].message_type = _GEOEVENT +_FEDERATEDEVENT.fields_by_name['contact'].message_type = _CONTACTLISTENTRY +_GEOEVENT.fields_by_name['binary'].message_type = _BINARYBLOB +_BINARYBLOB.fields_by_name['type'].enum_type = _BINARY_TYPES +_CONTACTLISTENTRY.fields_by_name['operation'].enum_type = _CRUD +_SUBSCRIPTION.fields_by_name['identity'].message_type = _IDENTITY +_CLIENTHEALTH.fields_by_name['status'].enum_type = _CLIENTHEALTH_SERVINGSTATUS +_CLIENTHEALTH_SERVINGSTATUS.containing_type = _CLIENTHEALTH +_SERVERHEALTH.fields_by_name['status'].enum_type = _SERVERHEALTH_SERVINGSTATUS +_SERVERHEALTH_SERVINGSTATUS.containing_type = _SERVERHEALTH +_ROL.fields_by_name['payload'].message_type = _BINARYBLOB +DESCRIPTOR.message_types_by_name['FederatedEvent'] = _FEDERATEDEVENT +DESCRIPTOR.message_types_by_name['GeoEvent'] = _GEOEVENT +DESCRIPTOR.message_types_by_name['BinaryBlob'] = _BINARYBLOB +DESCRIPTOR.message_types_by_name['ContactListEntry'] = _CONTACTLISTENTRY +DESCRIPTOR.message_types_by_name['Empty'] = _EMPTY +DESCRIPTOR.message_types_by_name['Identity'] = _IDENTITY +DESCRIPTOR.message_types_by_name['Subscription'] = _SUBSCRIPTION +DESCRIPTOR.message_types_by_name['ClientHealth'] = _CLIENTHEALTH +DESCRIPTOR.message_types_by_name['ServerHealth'] = _SERVERHEALTH +DESCRIPTOR.message_types_by_name['ROL'] = _ROL +DESCRIPTOR.enum_types_by_name['CRUD'] = _CRUD +DESCRIPTOR.enum_types_by_name['BINARY_TYPES'] = _BINARY_TYPES +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +FederatedEvent = _reflection.GeneratedProtocolMessageType('FederatedEvent', (_message.Message,), { + 'DESCRIPTOR' : _FEDERATEDEVENT, + '__module__' : 'fig_pb2' + # @@protoc_insertion_point(class_scope:com.atakmap.FederatedEvent) + }) +_sym_db.RegisterMessage(FederatedEvent) + +GeoEvent = _reflection.GeneratedProtocolMessageType('GeoEvent', (_message.Message,), { + 'DESCRIPTOR' : _GEOEVENT, + '__module__' : 'fig_pb2' + # @@protoc_insertion_point(class_scope:com.atakmap.GeoEvent) + }) +_sym_db.RegisterMessage(GeoEvent) + +BinaryBlob = _reflection.GeneratedProtocolMessageType('BinaryBlob', (_message.Message,), { + 'DESCRIPTOR' : _BINARYBLOB, + '__module__' : 'fig_pb2' + # @@protoc_insertion_point(class_scope:com.atakmap.BinaryBlob) + }) +_sym_db.RegisterMessage(BinaryBlob) + +ContactListEntry = _reflection.GeneratedProtocolMessageType('ContactListEntry', (_message.Message,), { + 'DESCRIPTOR' : _CONTACTLISTENTRY, + '__module__' : 'fig_pb2' + # @@protoc_insertion_point(class_scope:com.atakmap.ContactListEntry) + }) +_sym_db.RegisterMessage(ContactListEntry) + +Empty = _reflection.GeneratedProtocolMessageType('Empty', (_message.Message,), { + 'DESCRIPTOR' : _EMPTY, + '__module__' : 'fig_pb2' + # @@protoc_insertion_point(class_scope:com.atakmap.Empty) + }) +_sym_db.RegisterMessage(Empty) + +Identity = _reflection.GeneratedProtocolMessageType('Identity', (_message.Message,), { + 'DESCRIPTOR' : _IDENTITY, + '__module__' : 'fig_pb2' + # @@protoc_insertion_point(class_scope:com.atakmap.Identity) + }) +_sym_db.RegisterMessage(Identity) + +Subscription = _reflection.GeneratedProtocolMessageType('Subscription', (_message.Message,), { + 'DESCRIPTOR' : _SUBSCRIPTION, + '__module__' : 'fig_pb2' + # @@protoc_insertion_point(class_scope:com.atakmap.Subscription) + }) +_sym_db.RegisterMessage(Subscription) + +ClientHealth = _reflection.GeneratedProtocolMessageType('ClientHealth', (_message.Message,), { + 'DESCRIPTOR' : _CLIENTHEALTH, + '__module__' : 'fig_pb2' + # @@protoc_insertion_point(class_scope:com.atakmap.ClientHealth) + }) +_sym_db.RegisterMessage(ClientHealth) + +ServerHealth = _reflection.GeneratedProtocolMessageType('ServerHealth', (_message.Message,), { + 'DESCRIPTOR' : _SERVERHEALTH, + '__module__' : 'fig_pb2' + # @@protoc_insertion_point(class_scope:com.atakmap.ServerHealth) + }) +_sym_db.RegisterMessage(ServerHealth) + +ROL = _reflection.GeneratedProtocolMessageType('ROL', (_message.Message,), { + 'DESCRIPTOR' : _ROL, + '__module__' : 'fig_pb2' + # @@protoc_insertion_point(class_scope:com.atakmap.ROL) + }) +_sym_db.RegisterMessage(ROL) + + +DESCRIPTOR._options = None + +_FEDERATEDCHANNEL = _descriptor.ServiceDescriptor( + name='FederatedChannel', + full_name='com.atakmap.FederatedChannel', + file=DESCRIPTOR, + index=0, + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_start=1458, + serialized_end=2106, + methods=[ + _descriptor.MethodDescriptor( + name='SendOneEvent', + full_name='com.atakmap.FederatedChannel.SendOneEvent', + index=0, + containing_service=None, + input_type=_FEDERATEDEVENT, + output_type=_EMPTY, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='BinaryMessageStream', + full_name='com.atakmap.FederatedChannel.BinaryMessageStream', + index=1, + containing_service=None, + input_type=_BINARYBLOB, + output_type=_EMPTY, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='SendOneBlob', + full_name='com.atakmap.FederatedChannel.SendOneBlob', + index=2, + containing_service=None, + input_type=_BINARYBLOB, + output_type=_EMPTY, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='getIdentity', + full_name='com.atakmap.FederatedChannel.getIdentity', + index=3, + containing_service=None, + input_type=_EMPTY, + output_type=_IDENTITY, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='ClientEventStream', + full_name='com.atakmap.FederatedChannel.ClientEventStream', + index=4, + containing_service=None, + input_type=_SUBSCRIPTION, + output_type=_FEDERATEDEVENT, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='ServerEventStream', + full_name='com.atakmap.FederatedChannel.ServerEventStream', + index=5, + containing_service=None, + input_type=_FEDERATEDEVENT, + output_type=_SUBSCRIPTION, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='HealthCheck', + full_name='com.atakmap.FederatedChannel.HealthCheck', + index=6, + containing_service=None, + input_type=_CLIENTHEALTH, + output_type=_SERVERHEALTH, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='ClientROLStream', + full_name='com.atakmap.FederatedChannel.ClientROLStream', + index=7, + containing_service=None, + input_type=_SUBSCRIPTION, + output_type=_ROL, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='ServerROLStream', + full_name='com.atakmap.FederatedChannel.ServerROLStream', + index=8, + containing_service=None, + input_type=_ROL, + output_type=_SUBSCRIPTION, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), +]) +_sym_db.RegisterServiceDescriptor(_FEDERATEDCHANNEL) + +DESCRIPTOR.services_by_name['FederatedChannel'] = _FEDERATEDCHANNEL + +# @@protoc_insertion_point(module_scope) diff --git a/FreeTAKServer/model/protobufModel/group_pb2.py b/FreeTAKServer/model/protobufModel/group_pb2.py new file mode 100644 index 00000000..5c20768b --- /dev/null +++ b/FreeTAKServer/model/protobufModel/group_pb2.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: group.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='group.proto', + package='', + syntax='proto3', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x0bgroup.proto\"#\n\x05Group\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04role\x18\x02 \x01(\tb\x06proto3' +) + + + + +_GROUP = _descriptor.Descriptor( + name='Group', + full_name='Group', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='Group.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='role', full_name='Group.role', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=15, + serialized_end=50, +) + +DESCRIPTOR.message_types_by_name['Group'] = _GROUP +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Group = _reflection.GeneratedProtocolMessageType('Group', (_message.Message,), { + 'DESCRIPTOR' : _GROUP, + '__module__' : 'group_pb2' + # @@protoc_insertion_point(class_scope:Group) + }) +_sym_db.RegisterMessage(Group) + + +# @@protoc_insertion_point(module_scope) diff --git a/FreeTAKServer/model/protobufModel/precisionlocation_pb2.py b/FreeTAKServer/model/protobufModel/precisionlocation_pb2.py new file mode 100644 index 00000000..7344dd5c --- /dev/null +++ b/FreeTAKServer/model/protobufModel/precisionlocation_pb2.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: precisionlocation.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='precisionlocation.proto', + package='', + syntax='proto3', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x17precisionlocation.proto\"8\n\x11PrecisionLocation\x12\x13\n\x0bgeopointsrc\x18\x01 \x01(\t\x12\x0e\n\x06\x61ltsrc\x18\x02 \x01(\tb\x06proto3' +) + + + + +_PRECISIONLOCATION = _descriptor.Descriptor( + name='PrecisionLocation', + full_name='PrecisionLocation', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='geopointsrc', full_name='PrecisionLocation.geopointsrc', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='altsrc', full_name='PrecisionLocation.altsrc', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=27, + serialized_end=83, +) + +DESCRIPTOR.message_types_by_name['PrecisionLocation'] = _PRECISIONLOCATION +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +PrecisionLocation = _reflection.GeneratedProtocolMessageType('PrecisionLocation', (_message.Message,), { + 'DESCRIPTOR' : _PRECISIONLOCATION, + '__module__' : 'precisionlocation_pb2' + # @@protoc_insertion_point(class_scope:PrecisionLocation) + }) +_sym_db.RegisterMessage(PrecisionLocation) + + +# @@protoc_insertion_point(module_scope) diff --git a/FreeTAKServer/model/protobufModel/simple_pb2.py b/FreeTAKServer/model/protobufModel/simple_pb2.py new file mode 100644 index 00000000..5362adc2 --- /dev/null +++ b/FreeTAKServer/model/protobufModel/simple_pb2.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: simple.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='simple.proto', + package='', + syntax='proto3', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x0csimple.proto\",\n\x06Simple\x12\x10\n\x08\x65ndpoint\x18\x01 \x01(\t\x12\x10\n\x08\x63\x61llsign\x18\x02 \x01(\tb\x06proto3' +) + + + + +_SIMPLE = _descriptor.Descriptor( + name='Simple', + full_name='Simple', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='endpoint', full_name='Simple.endpoint', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='callsign', full_name='Simple.callsign', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=16, + serialized_end=60, +) + +DESCRIPTOR.message_types_by_name['Simple'] = _SIMPLE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Simple = _reflection.GeneratedProtocolMessageType('Simple', (_message.Message,), { + 'DESCRIPTOR' : _SIMPLE, + '__module__' : 'simple_pb2' + # @@protoc_insertion_point(class_scope:Simple) + }) +_sym_db.RegisterMessage(Simple) + + +# @@protoc_insertion_point(module_scope) diff --git a/FreeTAKServer/model/protobufModel/status_pb2.py b/FreeTAKServer/model/protobufModel/status_pb2.py new file mode 100644 index 00000000..722580f7 --- /dev/null +++ b/FreeTAKServer/model/protobufModel/status_pb2.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: status.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='status.proto', + package='', + syntax='proto3', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x0cstatus.proto\"\x19\n\x06Status\x12\x0f\n\x07\x62\x61ttery\x18\x01 \x01(\rb\x06proto3' +) + + + + +_STATUS = _descriptor.Descriptor( + name='Status', + full_name='Status', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='battery', full_name='Status.battery', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=16, + serialized_end=41, +) + +DESCRIPTOR.message_types_by_name['Status'] = _STATUS +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Status = _reflection.GeneratedProtocolMessageType('Status', (_message.Message,), { + 'DESCRIPTOR' : _STATUS, + '__module__' : 'status_pb2' + # @@protoc_insertion_point(class_scope:Status) + }) +_sym_db.RegisterMessage(Status) + + +# @@protoc_insertion_point(module_scope) diff --git a/FreeTAKServer/model/protobufModel/takcontrol_pb2.py b/FreeTAKServer/model/protobufModel/takcontrol_pb2.py new file mode 100644 index 00000000..44783fe4 --- /dev/null +++ b/FreeTAKServer/model/protobufModel/takcontrol_pb2.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: takcontrol.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='takcontrol.proto', + package='', + syntax='proto3', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x10takcontrol.proto\">\n\nTakControl\x12\x17\n\x0fminProtoVersion\x18\x01 \x01(\r\x12\x17\n\x0fmaxProtoVersion\x18\x02 \x01(\rb\x06proto3' +) + + + + +_TAKCONTROL = _descriptor.Descriptor( + name='TakControl', + full_name='TakControl', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='minProtoVersion', full_name='TakControl.minProtoVersion', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='maxProtoVersion', full_name='TakControl.maxProtoVersion', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=20, + serialized_end=82, +) + +DESCRIPTOR.message_types_by_name['TakControl'] = _TAKCONTROL +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TakControl = _reflection.GeneratedProtocolMessageType('TakControl', (_message.Message,), { + 'DESCRIPTOR' : _TAKCONTROL, + '__module__' : 'takcontrol_pb2' + # @@protoc_insertion_point(class_scope:TakControl) + }) +_sym_db.RegisterMessage(TakControl) + + +# @@protoc_insertion_point(module_scope) diff --git a/FreeTAKServer/model/protobufModel/takmessage_pb2.py b/FreeTAKServer/model/protobufModel/takmessage_pb2.py new file mode 100644 index 00000000..87f84f44 --- /dev/null +++ b/FreeTAKServer/model/protobufModel/takmessage_pb2.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: takmessage.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import cotevent_pb2 as cotevent__pb2 +import takcontrol_pb2 as takcontrol__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='takmessage.proto', + package='', + syntax='proto3', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x10takmessage.proto\x1a\x0e\x63otevent.proto\x1a\x10takcontrol.proto\"J\n\nTakMessage\x12\x1f\n\ntakControl\x18\x01 \x01(\x0b\x32\x0b.TakControl\x12\x1b\n\x08\x63otEvent\x18\x02 \x01(\x0b\x32\t.CotEventb\x06proto3' + , + dependencies=[cotevent__pb2.DESCRIPTOR,takcontrol__pb2.DESCRIPTOR,]) + + + + +_TAKMESSAGE = _descriptor.Descriptor( + name='TakMessage', + full_name='TakMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='takControl', full_name='TakMessage.takControl', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='cotEvent', full_name='TakMessage.cotEvent', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=54, + serialized_end=128, +) + +_TAKMESSAGE.fields_by_name['takControl'].message_type = takcontrol__pb2._TAKCONTROL +_TAKMESSAGE.fields_by_name['cotEvent'].message_type = cotevent__pb2._COTEVENT +DESCRIPTOR.message_types_by_name['TakMessage'] = _TAKMESSAGE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TakMessage = _reflection.GeneratedProtocolMessageType('TakMessage', (_message.Message,), { + 'DESCRIPTOR' : _TAKMESSAGE, + '__module__' : 'takmessage_pb2' + # @@protoc_insertion_point(class_scope:TakMessage) + }) +_sym_db.RegisterMessage(TakMessage) + + +# @@protoc_insertion_point(module_scope) diff --git a/FreeTAKServer/model/protobufModel/takv_pb2.py b/FreeTAKServer/model/protobufModel/takv_pb2.py new file mode 100644 index 00000000..65720baa --- /dev/null +++ b/FreeTAKServer/model/protobufModel/takv_pb2.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: takv.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='takv.proto', + package='', + syntax='proto3', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\ntakv.proto\"E\n\x04Takv\x12\x0e\n\x06\x64\x65vice\x18\x01 \x01(\t\x12\x10\n\x08platform\x18\x02 \x01(\t\x12\n\n\x02os\x18\x03 \x01(\t\x12\x0f\n\x07version\x18\x04 \x01(\tb\x06proto3' +) + + + + +_TAKV = _descriptor.Descriptor( + name='Takv', + full_name='Takv', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='device', full_name='Takv.device', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='platform', full_name='Takv.platform', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='os', full_name='Takv.os', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='version', full_name='Takv.version', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14, + serialized_end=83, +) + +DESCRIPTOR.message_types_by_name['Takv'] = _TAKV +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Takv = _reflection.GeneratedProtocolMessageType('Takv', (_message.Message,), { + 'DESCRIPTOR' : _TAKV, + '__module__' : 'takv_pb2' + # @@protoc_insertion_point(class_scope:Takv) + }) +_sym_db.RegisterMessage(Takv) + + +# @@protoc_insertion_point(module_scope) diff --git a/FreeTAKServer/model/protobufModel/track_pb2.py b/FreeTAKServer/model/protobufModel/track_pb2.py new file mode 100644 index 00000000..9347f0ba --- /dev/null +++ b/FreeTAKServer/model/protobufModel/track_pb2.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: track.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='track.proto', + package='', + syntax='proto3', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x0btrack.proto\"&\n\x05Track\x12\r\n\x05speed\x18\x01 \x01(\x01\x12\x0e\n\x06\x63ourse\x18\x02 \x01(\x01\x62\x06proto3' +) + + + + +_TRACK = _descriptor.Descriptor( + name='Track', + full_name='Track', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='speed', full_name='Track.speed', index=0, + number=1, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='course', full_name='Track.course', index=1, + number=2, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=15, + serialized_end=53, +) + +DESCRIPTOR.message_types_by_name['Track'] = _TRACK +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Track = _reflection.GeneratedProtocolMessageType('Track', (_message.Message,), { + 'DESCRIPTOR' : _TRACK, + '__module__' : 'track_pb2' + # @@protoc_insertion_point(class_scope:Track) + }) +_sym_db.RegisterMessage(Track) + + +# @@protoc_insertion_point(module_scope) diff --git a/FreeTAKServer/model/socketInformation.py b/FreeTAKServer/model/socketInformation.py new file mode 100644 index 00000000..884dd215 --- /dev/null +++ b/FreeTAKServer/model/socketInformation.py @@ -0,0 +1,4 @@ +class socketInformation: + def __init__(self): + self.socketCount = int() + self.clientArray = [] \ No newline at end of file diff --git a/FreeTAKServer/model/sockets/MainSocket.py b/FreeTAKServer/model/sockets/MainSocket.py new file mode 100644 index 00000000..0aef5271 --- /dev/null +++ b/FreeTAKServer/model/sockets/MainSocket.py @@ -0,0 +1,22 @@ +####################################################### +# +# MainSocket.py +# Python implementation of the Class MainSocket +# Generated by Enterprise Architect +# Created on: 21-May-2020 12:46:04 PM +# Original author: Natha Paquette +# +####################################################### +import socket + +class MainSocket: + def __init__(self): + self.ip = "0.0.0.0" + self.port = "" + self.sock = "" + self.socketAF = socket.AF_INET + self.socketSTREAM = socket.SOCK_STREAM + self.solSock = socket.SOL_SOCKET + self.soReuseAddr = socket.SO_REUSEADDR + self.sockProto = 1 + diff --git a/FreeTAKServer/model/sockets/TCPServerSocket.py b/FreeTAKServer/model/sockets/TCPServerSocket.py new file mode 100644 index 00000000..29008d00 --- /dev/null +++ b/FreeTAKServer/model/sockets/TCPServerSocket.py @@ -0,0 +1,4 @@ +from FreeTAKServer.model.sockets import MainSocket + +class TCPServerSocket(MainSocket): + pass \ No newline at end of file diff --git a/FreeTAKServer/model/sockets/__init__.py b/FreeTAKServer/model/sockets/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/FreeTAKServer/views/CLI.py b/FreeTAKServer/views/CLI.py index f6ed6755..8f3d7237 100644 --- a/FreeTAKServer/views/CLI.py +++ b/FreeTAKServer/views/CLI.py @@ -1,16 +1,12 @@ -import http +import http.client import json -from FreeTAKServer.controllers.CreateStartupFilesController import CreateStartupFilesController -from FreeTAKServer.controllers.Orchestrator import Orchestrator -from FreeTAKServer.controllers.DataPackageServer import FlaskFunctions +import tabulate from FreeTAKServer.controllers.configuration.RestAPIVariables import RestAPIVariables as vars -from FreeTAKServer.controllers.configuration.OrchestratorConstants import OrchestratorConstants from FreeTAKServer.controllers.configuration.DataPackageServerConstants import DataPackageServerConstants from FreeTAKServer.controllers.configuration.LoggingConstants import LoggingConstants from FreeTAKServer.controllers.CreateLoggerController import CreateLoggerController -from FreeTAKServer.controllers.AsciiController import AsciiController -from FreeTAKServer.controllers.model.FTS import FTS -from FreeTAKServer.controllers.model.RestAPIService import RestAPIService +from FreeTAKServer.model.ServiceObjects.FTS import FTS +from FreeTAKServer.model.ServiceObjects.RestAPIService import RestAPIService loggingConstants = LoggingConstants() logger = CreateLoggerController("CLI").getLogger() @@ -21,6 +17,7 @@ connectionIP = str(RestAPIService().RestAPIServiceIP) connectionPort = int(RestAPIService().RestAPIServicePort) +#TODO: standardize and abstract this class RestCLIClient: def __init__(self): @@ -43,13 +40,18 @@ def change_connection_info(self): def start_CoT_service(self): try: self.CoTIP = str( - input('enter CoT_service IP[' + str(OrchestratorConstants().IP) + ']: ')) or OrchestratorConstants().IP - self.CoTPort = input('enter CoT_service Port[' + str(OrchestratorConstants().COTPORT) + ']: ') or int( - OrchestratorConstants().COTPORT) + input('enter CoT_service IP[' + str(FTS().CoTService.CoTServiceIP) + ']: ')) or FTS().CoTService.CoTServiceIP + self.CoTPort = input('enter CoT_service Port[' + str(FTS().CoTService.CoTServicePort) + ']: ') or int( + FTS().CoTService.CoTServicePort) self.CoTPort = int(self.CoTPort) - #send start COT to API - body = json.dumps({"CoTService": {"IP": str(self.CoTIP), "PORT": int(self.CoTPort)}}) - self.conn.request("POST", "/CoTService", body, {"Content-type": "application/json", "Accept": "text/plain"}) + #send start COT + json_content.setdefaultCoTPort(self.CoTPort) + json_content.setdefaultCoTIP(self.CoTIP) + json_content.setdefaultCoTStatus('start') + body = json.dumps(json_content.getJsonStatusStartAll()) + conn = http.client.HTTPConnection(connectionIP, connectionPort) + conn.request("POST", "/changeStatus", body, {"Content-type": "application/json", "Accept": "text/plain"}) + response = conn.getresponse() if self.check_response(response): print('CoT service started') else: @@ -61,8 +63,11 @@ def start_CoT_service(self): def stop_CoT_service(self): try: - self.conn.request("DELETE", "/CoTService") - response = self.conn.getresponse() + json_content.setdefaultCoTStatus('stop') + body = json.dumps(json_content.getJsonStatusStartAll()) + conn = http.client.HTTPConnection(connectionIP, connectionPort) + conn.request("POST", "/changeStatus", body, {"Content-type": "application/json", "Accept": "text/plain"}) + response = conn.getresponse() if self.check_response(response): print('CoT service stopped') else: @@ -144,6 +149,36 @@ def stop_all(self): logger.error('there has been an exception in RestCLIClient stop_all ' + str(e)) return -1 + def show_DP(self): + try: + conn = http.client.HTTPConnection(connectionIP, connectionPort) + conn.request("GET", "/DataPackageTable") + response = conn.getresponse() + DataPackages = json.loads(response.read().decode("utf-8")) + DPArray = [] + for dict in DataPackages['json_list']: + values = list(dict.values()) + DPArray.append(values) + table = tabulate.tabulate(DPArray, headers = ["Keywords", "Name", "Index", "Privacy", "Size", "SubmissionDataTime", "SubmissionUser"], tablefmt='psql') + print(table) + return 1 + + except Exception as e: + logger.error("there has been an exception thrown in show DP function") + return -1 + + def remove_DP(self): + hash = input('Index of DataPackage to delete: ') + conn = http.client.HTTPConnection(connectionIP, connectionPort) + conn.request("DELETE", f"/DataPackageTable?Hash={hash}") + response = conn.getresponse() + DataPackages = json.loads(response.read().decode("utf-8")) + if self.check_response(response): + print('DP removed succesfully') + else: + print('DP removed failed') + return 1 + def help(self): print('start_all: to begin all services type') print('start_CoT_service: to begin CoT service type') @@ -153,7 +188,9 @@ def help(self): print('stop_data_package_service: to begin data package service type') print("change_connection_info: change the address and port of the server you're connecting to") print('show_users: to show connected user information type') - print('kill: to kill the full server type') + print('kill: terminate all the services') + print('show_DP: to show all DataPackages on the server') + print('remove_DP: to remove a DataPackages on the server') return 1 def check_service_status(self): @@ -190,14 +227,32 @@ def server_geochat(self): conn.request("POST", "/SendGeoChat", body, {"Content-type": "application/json", "Accept": "application/json"}) data = conn.getresponse() conn.close() - data = data.read().decode('utf-8') if self.check_response(data): print('geochat sent') + return 1 else: + return 1 print('geochat failed to send') except Exception as e: pass + def connection_message(self): + try: + conn = http.client.HTTPConnection(connectionIP, connectionPort) + text = input('enter message: ') + body = json.dumps({"detail": {'remarks': {"INTAG": text}}}) + conn.request("POST", "/ConnectionMessage", body, {"Content-type": "application/json", "Accept": "application/json"}) + data = conn.getresponse() + conn.close() + if self.check_response(data): + print('geochat sent') + return 1 + else: + print('geochat failed to send') + return 1 + except Exception as e: + pass + def verify_output(self, input, example=None): try: if example == None: @@ -232,19 +287,20 @@ def receive_input(self): self.UserCommand = str(input('FTS$ ')) or 'empty' try: function = getattr(self, self.UserCommand) - except: - logger.error('this is not a valid command') - functionOutput = function() - if self.verify_output(functionOutput): - pass - else: - raise Exception('function returned bad data') - except Exception as e: - logger.error('error in processing your request ' + str(e)) + functionOutput = function() + self.UserCommand = None + if self.verify_output(functionOutput): + pass + else: + raise Exception('function returned bad data') + except Exception as e: + print('error in processing your request ' + str(e)) + except: + logger.error('this is not a valid command') self.stop_all() if __name__ == "__main__": from FreeTAKServer.controllers.AsciiController import AsciiController AsciiController().ascii() - RestCLIClient().receive_input() \ No newline at end of file + RestCLIClient().receive_input() diff --git a/FreeTAKServer/views/__init__.py b/FreeTAKServer/views/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/README.md b/README.md index f8b1fc46..38a0876a 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,26 @@ It intends to support all the major use cases of the original TAK server. ## Community This code is currently in *BETA STAGE* Check out our roadmap @ FreeTakServer#25 to see what is planned -If you have any issues don't hesitate to bring it up https://github.com/Tapawingo/FreeTakServer/issues, as TAKFreeServer is still in the early stages of development. +If you have any issues don't hesitate to bring it up https://github.com/Tapawingo/FreeTakServer/issues, as TAKFreeServer is still in development. + +### Donate back +the FTS team is working daily on the development of a open and free solution. We plan to do more that simply replicate the functionalities of the legacy TAK server, our road map includes integration with open source systems like LORA's Meshtastic, porting it to Android, having an open API and much more. + +We are doing it for free because we believe that donating personal time to a cause its a endeavour that is worthy per-se, However, a part time, we are also spending our own money to: +- Maintain a Public server and a test server +- Investing in different technologies for R&D + +if you feel that FTS is useful to you and you can donate in those challenging times please consider to send you contribution here: +[DONATE](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=brothercorvo%40gmail.com&item_name=FreeTAKServer+R%26D¤cy_code=CAD&source=url) + +You can also support the project by buying one of our [t-shirts](http://tee.pub/lic/elARpZYCmaw) + +NOTE: +not a big fan of Paypal, but that is the easier way I found for an initial attempt. We may go to some more ethical system in future. ### Public instance -we support a public instance of FTS. -- download the configuration here -https://drive.google.com/open?id=1IK1LfPN13EWikHaMyOuDDwIerNGz-Wli +we support a [public instance}(https://www.reddit.com/r/ATAK/wiki/index/freetakserver) of FTS. +- download the configuration {here}(https://drive.google.com/open?id=1IK1LfPN13EWikHaMyOuDDwIerNGz-Wl) - use the Import manager in ATAK to import the configuration ### Tell us what you think! @@ -32,18 +46,22 @@ https://discordapp.com/invite/XEPyhHA ## Architecture TAKFreeServer uses a MVC pattern, the concept of a COT is described in a set of Domain classes, generated from the UML model using a Model Driven Architecture approach. -![the domain model with all the know objects used by CIVTAK/ wintak](https://github.com/Tapawingo/TAKlib/blob/master/docs/FreeTakServer%20specs/FreeTAKServer%20Model.png?raw=true) -The target architecture supports also the ability to implement "plugins", thanks to a listener, that is decouple from the main server -![the FreeTakServer component model](https://github.com/Tapawingo/TAKlib/blob/master/docs/FreeTakServer%20specs/FreeTakServerComponents.png?raw=true) +![the domain model with all the know objects used by CIVTAK/ wintak](https://github.com/FreeTAKTeam/FreeTakServer/blob/master/docs/FreeTAKServer%20Model.png) +YOu can see the complete COT description {here}(https://github.com/FreeTAKTeam/FreeTakServer/blob/master/docs/FreeTakServer%20specs/COTDomainModel.pdf) ## Documentation -under docs, you can find various documents including an UMl model of the model classes involved in a COT event. +under docs, you can find various documents including an UML model of the Domain classes involved in a COT event. ## Requirements - Python 3.6 (or better) ## Installing and using FreeTakServer +Important Note: depending from the system you are using, the following commands may be executed using python3, Pip3 or in alternative python, Pip (without the 3). + + ### Prerequisites +you will need to install Python 3, PIP before you can install FTS + - Install Python3 ``` sudo apt update && sudo apt install python3 && sudo apt install pip3` (Ubuntu)``` @@ -52,12 +70,12 @@ under docs, you can find various documents including an UMl model of the model c Since version 0.8, FTS supports Pip installation, manual installation can be done with some modifications of the import paths, however we don't support it ``` - pip3 install FreeTAKServer +sudo python -m pip install FreeTAKServer ``` -Optional: check if installation is correctly executed +Optional: check if installation is correctly executed and install any missing packages if prompted ``` -pip check FreeTakServer +sudo python -m pip check FreeTakServer ``` note under windows it's installed under @@ -69,57 +87,44 @@ C:\Users\user.name\AppData\Local\Programs\Python\PythonXX\Lib\site-packages ### Linux -#### Configuration - -it is recomended to edit the maximum number of open connections with the following -``` -vim /etc/sysctl.conf -fs.file-max = 200000 -sysctl -p -``` - #### Run Server in console ``` -sudo python3 -m FreeTAKServer.controllers.FTS -AutoStart (weather the full server start or just the RestAPI, must be True or False) -CoTIP (your IP) -DataPackageIP(your IP) -CoTPort (the port you want atak to connect to) -DataPackagePort (the port you want datapackages to be sent and received on) -``` - +sudo python3 -m FreeTAKServer.controllers.services.FTS -DataPackageIP [YourIP] ``` -defaults: +this will start the server with Port 8087 and API port 8080 on the IP defined in [yourIP] -AutoStart = True +other parameters you can use: +-AutoStart: (weather the full server start or just the RestAPI, must be True or False) + -CoTIP [yourIP] + -DataPackageIP[yourIP] : set the IP where CoTs are send + -CoTPort [aPort] : the port you want clients to connect to + -DataPackagePort [anotherPort]: the port you want datapackages to be sent and received on + +if you dont set any of the above, FTS will adopt a "Convention instead of Configuration" approach and try to set all from the configuation file -CoTIP = 0.0.0.0 - -DataPackageIP = 0.0.0.0 - -DataPackagePort = 8080 - -CoTPort = 8087 +Open a new console in a separate window +run FTS Command Line Interface with +``` +python -m FreeTAKServer.views.CLI ``` -this will start the program in an emulated terminal like enviroment +to get a list of other supported commands type -### Run CLI in console +```help``` -``` -sudo python3 -m FreeTAKServer.views.CLI -``` -to start the commandline +#### Run Server as Demon +use this command to run FTS independently from your command window. ``` -help +sudo nohup python3 -m FreeTAKServer.controllers.FTS -DataPackageIP [YourIP] & ``` -to get a list of other supported commands run the above command - -it is recommended to start the server with start_all - ### Windows go to the start menu and type cmd to start a command prompt open a console with admin rights ``` -python3 -m FreeTAKServer.controllers.FTS +python3 -m FreeTAKServer.controllers.FTS -DataPackageIP [YourIP] ``` ### Troubleshooting @@ -135,11 +140,27 @@ if you already installed FTS with pip you can use pip install FreeTAKServer --upgrade ``` + +### client2client datapackages + +If you have issues sending datapackages directly to clients via FTS, make sure -IP you specified can be reached from your device. +A quick way to test if it works is to take a picture with Quick Pic in ATAK and send it to another client. Please also note that for that test ATAK clients needs to be on different network (ie one on mobile and one on wifi), because if you run them in same network (wifi, vpn, etc) they will just use same multicast group, bypassing FTS completely. +When you post package to specific contact in ATAK, following happens: + + 1) Datapackage is uploaded to server, recorded in database and stored in FTS directory + 2) Client receives payload with URL pointing to datapackage so ATAK can download it + +Assuming you want to run open-to-everyone FTS instance, and you have server hosted somewhere, you need to specify _public_ IP address in -IP argument. And just in case, -IP also accepts domain names. +If you run it at home and port forward on router doesn't work, check if you receive actual IP address and not being NATed and ports 8080 and 8087 are not filtered - you can ask your ISP about that. + + + ## Project Structure - TakFreeServer - **Controllers**: Contains all the business Logic - **Models**: Contains all the COT object model - - **configuration**: Contains constants and configuration files for FTS + - **TAKLinuxService**: a demon for linux OS + - **TakWinService**: a service for the windows OS - Docs: Usefull documentation regarding COTS and different logs to understand how those are implemented - Model: a UML model in Sparx EnterpriseArchitect format (see https://sparxsystems.com/products/ea/trial/request.html). - Old: Legacy versions diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..07de284a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" \ No newline at end of file diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 00000000..e1effeb8 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,16 @@ +[metadata] +name = "FreeTAKServer" +version = 1.1 +description-file = README.md + +[options] +packages = "FreeTAKServer" +install_requires = + requests + importlib + flask + sqlalchemy + tabulate + pathlib + lxml + Flask_SQLAlchemy diff --git a/setup.py b/setup.py index c56fea9a..cbd880e3 100644 --- a/setup.py +++ b/setup.py @@ -1,32 +1,38 @@ from setuptools import find_packages, setup from os import path + this_directory = path.abspath(path.dirname(__file__)) with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f: long_description = f.read() setup( - name = 'FreeTAKServer', # How you named your package folder (MyLib) - packages = ['FreeTAKServer', 'FreeTAKServer.controllers', 'FreeTAKServer.controllers.configuration', 'FreeTAKServer.controllers.model'], # Chose the same as "name" - version = '0.8.76', # Start with a small number and increase it with every change you make - license='MIT', # Chose a license from here: https://help.github.com/articles/licensing-a-repository - description = 'An open source server for the TAK family of applications.', # Give a short description about your library - long_description=long_description, - long_description_content_type='text/markdown', - author = 'Ghosty 1008', # Type in your name - author_email = 'your.email@domain.com', # Type in your E-Mail - url = 'https://github.com/Tapawingo/FreeTakServer', # Provide either the link to your github or to your website - download_url = 'https://github.com/Tapawingo/FreeTakServer/archive/v0.8.4-Beta.tar.gz', # I explain this later on - keywords = ['TAK', 'OPENSOURCE'], # Keywords that define your package best - install_requires=[ # I get to this in a second - 'flask', - 'lxml', - 'pathlib', - ], - classifiers=[ - 'Development Status :: 4 - Beta', # Chose either "3 - Alpha", "4 - Beta" or "5 - Production/Stable" as the current state of your package - 'Intended Audience :: Developers', # Define that your audience are developers - 'Topic :: Software Development :: Build Tools', - 'License :: OSI Approved :: MIT License', # Again, pick a license - 'Programming Language :: Python :: 3.6', - ], + name='FreeTAKServer', + packages=find_packages(include = ['FreeTAKServer', 'FreeTAKServer.*']), + version='1.1', + license='MIT', + description='An open source server for the TAK family of applications.', + + long_description=long_description, + long_description_content_type='text/markdown', + author='Ghosty 1008', + author_email='your.email@domain.com', + url='https://github.com/Tapawingo/FreeTakServer', + download_url='https://github.com/Tapawingo/FreeTakServer/archive/v0.8.4-Beta.tar.gz', + keywords=['TAK', 'OPENSOURCE'], + install_requires=[ + 'flask', + 'lxml', + 'pathlib', + 'tabulate', + 'sqlalchemy', + 'setuptools', + 'Flask_SQLAlchemy' + ], + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'Topic :: Software Development :: Build Tools', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python :: 3.6', + ], ) \ No newline at end of file