{"id":15009999,"url":"https://github.com/il2horusteam/il2fb-ds-airbridge","last_synced_at":"2025-04-09T17:54:06.110Z","repository":{"id":53534612,"uuid":"101282770","full_name":"IL2HorusTeam/il2fb-ds-airbridge","owner":"IL2HorusTeam","description":"Wrapper of dedicated server of «IL-2 Sturmovik: Forgotten Battles». Provides high-level API and streaming facilities","archived":false,"fork":false,"pushed_at":"2021-03-25T21:57:26.000Z","size":1518,"stargazers_count":5,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-23T20:01:36.610Z","etag":null,"topics":["aiohttp","api","asyncio","aviation","il2","nats","nats-streaming","proxy","python","python-3-6","python3","subprocess","terminal","websocket"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/IL2HorusTeam.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-08-24T10:23:50.000Z","updated_at":"2022-12-01T17:58:28.000Z","dependencies_parsed_at":"2022-08-20T13:01:04.869Z","dependency_job_id":null,"html_url":"https://github.com/IL2HorusTeam/il2fb-ds-airbridge","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IL2HorusTeam%2Fil2fb-ds-airbridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IL2HorusTeam%2Fil2fb-ds-airbridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IL2HorusTeam%2Fil2fb-ds-airbridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IL2HorusTeam%2Fil2fb-ds-airbridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/IL2HorusTeam","download_url":"https://codeload.github.com/IL2HorusTeam/il2fb-ds-airbridge/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248083558,"owners_count":21045122,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aiohttp","api","asyncio","aviation","il2","nats","nats-streaming","proxy","python","python-3-6","python3","subprocess","terminal","websocket"],"created_at":"2024-09-24T19:29:25.414Z","updated_at":"2025-04-09T17:54:06.093Z","avatar_url":"https://github.com/IL2HorusTeam.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"IL-2 FB Dedicated Server Airbridge\n##################################\n\n|pypi_package| |python_versions| |license| |codebeat| |codacy| |scrutinizer|\n\n|logo|\n\n\n**Table of Contents**\n\n.. contents::\n    :local:\n    :depth: 3\n    :backlinks: none\n\n\nGlossary\n========\n\nDefinitions below give explanation of terms used in this text. Some\nexplanations may slightly differ from generally-accepted because of\ndomain-specific aspects.\n\nIL-2 FB\n    \"Old\" version of «IL-2 Sturmovik» aviasimulator. It is often referenced\n    as «IL-2 Sturmovik: Forgotten Battles», however it also implies all\n    further commercial versions up to «IL-2 Sturmovik: 1946» including all\n    official free patches.\n\nDS\n    Dedicated server of IL-2 FB: a stand-alone headless application which is\n    used for creation of a single entry point for multiplayer game mode.\n\nAPI\n    Application's interface which makes it possible for 3rd-party software to\n    interact with the application.\n\nTelnet\n    A network protocol which provides a bidirectional interactive text-oriented\n    communication facility using a virtual terminal connection.\n\nConsole\n    Server's terminal (shell) which is used by server's administrators to\n    manage server by executing text commands and to monitor several aspects of\n    users' activity like connections to DS, chat messages and so on. Console\n    is also an API served by server over Telnet protocol to provide terminal\n    access to 3rd-party software.\n\nDevice Link\n    A game-specific network protocol and API which is generally used to access\n    current state of players' aircrafts by 3rd-party software. For DS it\n    provides ability to query coorinates of all actors and static objects in\n    nearly real-time fashion. `Refer to documentation \u003chttps://docs.google.com/document/d/1mIAa-sMQhLFyHgDdRpABwFZ9TW0Yxcwr9Lc2jTmTGtI/edit?usp=sharing\u003e`_\n    for more details.\n\nMission\n    A text file which contains definition of game environment, objects, actors,\n    targets and so on. Mission is also a process of execution of mission file,\n    i.e. a running game. `Refer to demo page of mission parser \u003chttp://il2horusteam.github.io/il2fb-mission-parser/\u003e`_\n    to get example of mission definition.\n\nGame Log\n    A text file produced by DS which stores in-game events each of which is\n    recorded in an append-only mode. Each event represents a set of changes\n    in state of actors in mission. `Refer to demo page of game log parser \u003chttp://il2horusteam.github.io/il2fb-game-log-parser/\u003e`_\n    to get examples of event records.\n\nServer Config\n    A text file which defines server's technical characteristics, facilities\n    and global game options. `Refer to configuration editor \u003chttps://il2horusteam.github.io/il2fb-ds-config/\u003e`_\n    for more details.\n\nStreaming\n    A process of continuous sharing of data from producer to direct consumer or\n    storage.\n\nPub/Sub\n    Publish–subscribe is a communication pattern where senders of messages know\n    nothing about message receivers, as communication is provided by a mediator\n    called \"message broker\" or \"message bus\". This pattern allows to totally\n    decouple senders from receivers, hence, they do not need to know about\n    existence, location, availability and implementation of each other.\n\nHTTP\n    Request–response communication protocol in the client–server computing\n    model, where messages are presented as structured text. Designed for\n    transfer of hypermedia text (HTML). It is the foundation of any data\n    exchange on the Web.\n\nREST\n    REST (REpresentational State Transfer) is an architectural style, and an\n    approach to communications that is often used in the development of Web\n    services. The key abstraction of information in REST is a resource. Other\n    important thing associated with REST is resource methods to be used to\n    perform the desired transition of resource's state. Usually implemented on\n    top of HTTP, but not limited to it.\n\nWS\n    WebSockets is a communications protocol, providing full-duplex\n    communication channels between a client and a server. It makes it possible\n    to send messages to a server and receive event-driven responses without\n    having to poll the server for a reply. WebSockets protocol was designed to\n    work over HTTP and allows web application to communicate with server\n    directly from web browser.\n\nNATS\n    NATS is a high performance messaging system that acts as a distributed\n    messaging queue for cloud native applications\n    (`see more info \u003chttp://nats.io\u003e`_).\n\nNATS Streaming\n    NATS Streaming is a data streaming system powered by NATS\n    (`see more info \u003chttps://nats.io/documentation/streaming/nats-streaming-intro/\u003e`_).\n\n\nSynopsis\n========\n\nAirbridge is an application which wraps dedicated server of\n«IL-2 Sturmovik: Forgotten Battles» aviasimulator.\n\nIt acts as additional access layer on top of dedicated server and provides\nhigh-level API with ability to subscribe to game events. Airbridge makes it\npossible to communicate with dedicated server by exchanging structured messages\ninstead of raw strings and packages.\n\nThis means that you can access server's console, device link and mission\nstorage in a unified way. Also it's possible to subscribe to the stream of\nparsed game events easily.\n\nAirbridge allows totally remote access to dedicated server without need to\nbother about access to server's file system. This allows to escape limitations\non location of supplementary software and server commanders: dedicated server\nand 3rd-party software can now run on different machines and under different\noperating systems.\n\nAll that brings much easier server's API and more pleasant development\nexperience.\n\n\nRationale\n=========\n\nThe main rationale behind this project is a need for convenient unified\nprogrammatic access to different facilities of dedicated server along with\nability to monitor users' in-game activity and to manage server remotely.\n\nDedicated server exposes multiple facilities to 3rd-party applications:\nmanagement console, location service, mission storage, config, streaming of\nin-game events, etc. All these facilities require different ways of\ncommunication and use different data structured for that, which are not\ndocumented. This makes it difficult, tedious and error-prone to build systems\non top of bare dedicated server, especially server commanders. Developers of\nevery commander have to invent their own toolset for accessing same\nserver's facilities. This results in duplication of code and different\nimplementations for different programming languages.\n\nAirbridge unifies API to server's facilities and uses structured messages for\ncommunication instead of raw strings or bytes. It provides API consistency\nand development comfort. Access to  each facility is done via corresponding\nstand-alone library, e.g.\n`il2fb-ds-middleware \u003chttps://github.com/IL2HorusTeam/il2fb-ds-middleware\u003e`_,\n`il2fb-game-log-parser \u003chttps://github.com/IL2HorusTeam/il2fb-game-log-parser\u003e`_,\n`il2fb-mission-parser \u003chttps://github.com/IL2HorusTeam/il2fb-mission-parser\u003e`_\nand `il2fb-ds-config \u003chttps://github.com/IL2HorusTeam/il2fb-ds-config\u003e`_.\nThese libraries accumulate almost all knowledge of their subjects and can be\nused separately. Community can contrubite to their development and free up\nmuch of resources by reusing these libraries. Airbridge aggregates These\nlibraries and exposes their functionality on top of a running dedicated server.\n\nDedicated server allows only one application to access its management console\nat a time. Moreover, storage of game events (game log) is sticked to server's\nfile system making it impossible to access events outside server. Same is right\nfor mission storage: if missions are genarated by 3rd-party software, they need\nto be uploaded to server's mission storage, but there is no way to do this.\nAll that results into creation of heavy monolithic applications which combine\napplication's logic, communication with game server and external services like\ndatabases, web applications and mission generators into a complex one-stop\nshop.\n\nAdditionally, most of dedicated servers run on dedicated hardware along with\nother services under Windows OS. This is quite not the best OS for running\ncomplex systems and it's definitely not suitable for development of them.\n\nAirbridge allows developes of 3rd-party software to escape single machine and\nWindows OS giving them ability to bring more power and flexibility to\ncomputation, logic and infrastructure of their systems.\n\n\nArchitecture Overview\n=====================\n\nThe diagram below depicts architecture of Airbridge application for better\nunderstanding of its implementation and work principles.\n\n.. image:: ./docs/Overview.png\n   :alt: Architecture Overview\n   :align: center\n\n\nAirbridge application runs dedicated server in background as a coprocess. It\ncaptures server's STDOUT with STDIN and forwards it to own STDOUT with STDIN.\nSTDIN of Airbridge is forwarded to server's STDIN. This allows to do analysis\nand filtering of terminal I/O, e.g. addition of colors for prompt and errors.\nFrom user's perspective there's no visible difference between work with bare\nserver and work with Airbridge. This is good for compatibility reasons.\n\nInformation about server's config is provided to Airbridge by\n`il2fb-ds-config \u003chttps://github.com/IL2HorusTeam/il2fb-ds-config\u003e`_ library.\nMost important config options are related to console's and device link's ports\nand location of game log. Location of missions is always known and contained\ninside server's directory.\n\nCommunication between Airbridge and dedicated server is provided by device link\nand console clients (see `il2fb-ds-middleware \u003chttps://github.com/IL2HorusTeam/il2fb-ds-middleware\u003e`_ library).\nThey allow to perform high-level requests as well as to send raw data. The\nlatter one is used to build appropriate proxies on top of clients. Proxies\nallow existing applications to continue to communicate with server without\nchanges. At the same time new applications can use unified API of Airbridge\nwithout any need to bother themselves with knowledge about low-level protocols.\n\nDevice link on dedicated server can be used only to locate coordinates of\nactors and buildings. As location of objects is done by execution of multiple\nrequests to server's device link, a ``radar`` is build on top of its client to\nsimplify location of different types of objects.\n\nGame log of dedicated server is monitored by a game log watcher. If new records\nappear in game log, the watcher will read them and pass to a game log parser\n(see `il2fb-game-log-parser \u003chttps://github.com/IL2HorusTeam/il2fb-game-log-parser\u003e`_ library).\nThe parser emits structured representation of events. It also emits not parsed\nstrings if it failes to parse them. This can be used to track parsing errors\nwhich can occur if a new or unknown event happens. Such events can be stored\nand used for improving parser.\n\nAll features of dedicated server can be separated into two categories: requests\nand streaming. Requests are made via radar or console client. Streaming is a\nbit more compticated as events of a single logical facility can come from\ndifferent physical souces (i.e. events mainly come from game log but can come\nfrom console client as well).\n\nThere are four logical facilities which bring streaming to their subscribers:\n``chat``, ``events``, ``not parsed strings`` and ``radar``. The first three\nfacilities act as routers between data sources and subscribers: ``chat``\nfacility subscribes to chat messages from console client and broadcasts them to\nchat subscribers; ``events`` facility subscribes to game events from game log\nparser and to user connection events from console client and broadcasts events\nto events subscribers; ``not parsed strings`` facility subscribes to strings\nproduced by game log parser and broadcasts them to own subscribers.\nIn contrast, ``radar`` facility does not route data from other sources.\nInstead, it produces it by querying radar component periodically. Period of\nquerying depends on the needs of its subscribers.\n\nSubscribers in terms of Airbridge are any objects who follow its subscription\ninterface. Subscribers can be static and dynamic: static subscribers are\ncreated when application starts and work until it exits; dynamic subscribers\ncan be created and destroyed at any moment. For example, it's possible to\ncreate a file streaming subscriber or NATS streaming subscriber which will work\nfrom application's startup till its end. Also it's possible to connect to\nAirbridge via WebSocket and subscribe to facilities dynamically.\n\nClients of Airbridge can perform requests via different APIs depending on their\nneeds. They can use Request-Reply API over NATS or REST API over HTTP.\n\nREST API combines two independent parts: API for dedicated server and API for\nmissions storage. In fact, these APIs can be separated from each other and live\ntheir independent lives in different services (splitted into microservices),\nbut this does not make sense at this point due to maintenance overhead.\n\n\nFeatures Overview\n=================\n\nThis section provides an overview of features which Airbridge brings to its\nusers. As it was already mentioned in the previous section, all features can\nbe devided into two categories: requests and streaming.\n\n\nRequests\n--------\n\nRequests are used to query data or to change state of processes and objects.\nThey can have or not have responses depending on their type.\n\nAll requests which interact with dedicated server accept optional parameter\n``timeout``. It has type ``float`` and is measured in seconds.\n\nIn contrast with raw server's communication interfaces, requests API of\nAirbridge provides seamless multiplexing of requests comming from multiple\nclients.\n\n\nREST\n~~~~\n\nThe following part of documentation lists and describes REST API endpoints\nwhich are available over HTTP.\n\nBodies of POST requests and responses of all requests are formatted as JSON.\n\nAll endpoints accept optional ``pretty`` query parameter. For example:\n``/info?pretty``. It tells endpoints to make \"pretty\" output by adding\nindents. This can be useful for debugging.\n\nTimeouts are passed as query parameters also, e.g.: ``/info?timeout=3``\n\n``GET /``\n    Check status of Airbridge and dedicated server. Can be useful for health\n    checking and failure detection with tools like\n    `Consul \u003chttps://www.consul.io\u003e`_.\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            Server is alive.\n\n            Example\n                .. code-block:: json\n\n                    {\n                        \"status\": \"alive\"\n                    }\n\n    Authorization\n        No authorization.\n\n\n``GET /info``\n    Get information about server. Wraps ``server`` console command.\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            Serialized `il2fb.ds.middleware.console.structures.ServerInfo \u003chttps://github.com/IL2HorusTeam/il2fb-ds-middleware/blob/master/il2fb/ds/middleware/console/structures.py#L10\u003e`_\n            structure.\n\n            Example\n                .. code-block:: json\n\n                    {\n                        \"type\": \"Local server\",\n                        \"name\": \"Development server\",\n                        \"description\": \"Dedicated Server for local tests\",\n                        \"__type__\": \"il2fb.ds.middleware.console.structures.ServerInfo\"\n                    }\n\n    Authorization\n        No authorization.\n\n\n``GET /humans``\n    Get list of users connected to server. Wraps ``user`` console command.\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            List of `il2fb.ds.middleware.console.structures.Human \u003chttps://github.com/IL2HorusTeam/il2fb-ds-middleware/blob/master/il2fb/ds/middleware/console/structures.py#L27\u003e`_\n            structures.\n\n            Example\n                .. code-block:: json\n\n                    [\n                        {\n                            \"callsign\": \"john.doe\",\n                            \"ping\": 15,\n                            \"score\": 0,\n                            \"belligerent\": {\n                                \"name\": \"red\",\n                                \"value\": 1,\n                                \"verbose_name\": \"red\",\n                                \"help_text\": null\n                            },\n                            \"aircraft\": {\n                                \"designation\": \"* Red 1\",\n                                \"type\": \"Yak-1\"\n                            },\n                            \"__type__\": \"il2fb.ds.middleware.console.structures.Human\"\n                        }\n                    ]\n\n    Authorization\n        Required if configured.\n\n\n``GET /humans/count``\n    Get number of users connected to server. Equals to a number of records\n    returned by ``user`` console command.\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            Integer representing number of connected users.\n\n            Example\n                .. code-block:: json\n\n                    7\n\n    Authorization\n        Required if configured.\n\n\n``GET /humans/statistics``\n    Get server's statistics for users connected to server.\n    Wraps ``user STAT`` console command.\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            List of `il2fb.ds.middleware.console.structures.HumanStatistics \u003chttps://github.com/IL2HorusTeam/il2fb-ds-middleware/blob/master/il2fb/ds/middleware/console/structures.py#L45\u003e`_\n            structures.\n\n            Example\n                .. code-block:: json\n\n                    [\n                        {\n                            \"callsign\": \"john.doe\",\n                            \"score\": 0,\n                            \"state\": \"Landed at Airfield\",\n                            \"enemy_aircraft_kills\": 0,\n                            \"enemy_static_aircraft_kills\": 0,\n                            \"enemy_tank_kills\": 0,\n                            \"enemy_car_kills\": 0,\n                            \"enemy_artillery_kills\": 0,\n                            \"enemy_aaa_kills\": 0,\n                            \"enemy_wagon_kills\": 0,\n                            \"enemy_ship_kills\": 0,\n                            \"enemy_radio_kills\": 0,\n                            \"friendly_aircraft_kills\": 0,\n                            \"friendly_static_aircraft_kills\": 0,\n                            \"friendly_tank_kills\": 0,\n                            \"friendly_car_kills\": 0,\n                            \"friendly_artillery_kills\": 0,\n                            \"friendly_aaa_kills\": 0,\n                            \"friendly_wagon_kills\": 0,\n                            \"friendly_ship_kills\": 0,\n                            \"friendly_radio_kills\": 0,\n                            \"bullets_fired\": 0,\n                            \"bullets_hit\": 0,\n                            \"bullets_hit_air_targets\": 0,\n                            \"rockets_launched\": 0,\n                            \"rockets_hit\": 0,\n                            \"bombs_dropped\": 0,\n                            \"bombs_hit\": 0,\n                            \"__type__\": \"il2fb.ds.middleware.console.structures.HumanStatistics\"\n                        }\n                    ]\n\n    Authorization\n        Required if configured.\n\n\n``POST /humans/kick``\n    Kick all users from server.\n\n    Responses\n        ``200``\n            Empty dictionary.\n\n            Example\n                .. code-block:: json\n\n                    {}\n\n    Authorization\n        Required if configured.\n\n\n``POST /humans/\u003ccallsign\u003e/kick``\n    Kick user from server by user's callsign.\n\n    Parameters\n        In URL\n            ``callsign``\n                Callsign of user to kick.\n\n                Type\n                    ``string``\n\n                Example\n                    ``/humans/john.doe/kick``\n\n    Responses\n        ``200``\n            Empty dictionary.\n\n            Example\n                .. code-block:: json\n\n                    {}\n\n    Authorization\n        Required if configured.\n\n\n``POST /chat``\n    Send message in chat to everyone.\n\n    Parameters\n        In body\n            ``message``\n                Message to send.\n\n                Type\n                    ``string``\n\n            Body example\n                .. code-block:: json\n\n                    {\n                        \"message\": \"hello!\"\n                    }\n\n    Responses\n        ``200``\n            Empty dictionary.\n\n            Example\n                .. code-block:: json\n\n                    {}\n\n    Authorization\n        Required if configured.\n\n\n``POST /chat/humans/\u003caddressee\u003e``\n    Send message in chat to a user.\n\n    Parameters\n        In URL\n            ``addressee``\n                Callsign of user to chat to.\n\n                Type\n                    ``string``\n\n                Example:\n                    ``/chat/humans/john.doe``\n\n        In body\n            ``message``\n                Message to send.\n\n                Type\n                    ``string``\n\n            Body example\n                .. code-block:: json\n\n                    {\n                        \"message\": \"hello!\"\n                    }\n\n    Responses\n        ``200``\n            Empty dictionary.\n\n            Example\n                .. code-block:: json\n\n                    {}\n\n    Authorization\n        Required if configured.\n\n\n``POST /chat/belligerents/\u003caddressee\u003e``\n    Send message in chat to a belligerent (army).\n\n    Parameters\n        In URL\n            ``addressee``\n                Belligerent to chat to. See `il2fb.commons.organization.Belligerents \u003chttps://github.com/IL2HorusTeam/il2fb-commons/blob/master/il2fb/commons/organization.py#L20\u003e`_\n                for details.\n\n                Type\n                    ``integer``\n\n                Example:\n                    ``/chat/belligerents/1``\n\n        In body\n            ``message``\n                Message to send.\n\n                Type\n                    ``string``\n\n            Body example\n                .. code-block:: json\n\n                    {\n                        \"message\": \"hello!\"\n                    }\n\n    Responses\n        ``200``\n            Empty dictionary.\n\n            Example\n                .. code-block:: json\n\n                    {}\n\n    Authorization\n        Required if configured.\n\n\n``GET /missions/\u003cpath\u003e``\n    Browse missions storage (directories, ``.mis`` and ``.properties`` files).\n\n    Parameters\n        In URL\n            ``path``\n                Path to a directory or mission relative to server's\n                ``Missions`` directory. ``Missions`` root directory is used if\n                ``path`` is not specified.\n\n                Type\n                    ``string``\n\n                Example for directory\n                    ``/missions/Net/dogfight``\n\n                Example for mission\n                    ``/missions/Net/dogfight/demo_sample.mis``\n\n        In query:\n            ``json``\n                Optional parameter for getting parsed mission instead of raw\n                text. Parsing is done by `il2fb-mission-parser \u003chttps://github.com/IL2HorusTeam/il2fb-mission-parser\u003e`_\n                library.\n\n            Type\n                ``string``\n\n            Example\n                ``/missions/Net/dogfight/demo_sample.mis?json``\n\n    Responses\n        ``200``\n            List of files and directories if resource is a directory.\n\n            Example\n                .. code-block:: json\n\n                    {\n                        \"dirs\": [\n                            \"   1\",\n                            \"   2\",\n                            \"   3\",\n                            \"   4\",\n                            \"Pacific Fighters\"\n                        ],\n                        \"files\": [\n                            \"demo_sample.mis\",\n                            \"demo_sample_ru.properties\"\n                        ]\n                    }\n\n        ``200``\n            Mission content as plain text if resource is a mission.\n\n        ``200``\n            Parsed mission content as JSON if resource is a mission and\n            ``json`` parameter is specified.\n            `Refer to parser's demo page \u003chttp://il2horusteam.github.io/il2fb-mission-parser/\u003e`_\n            to explore resulting format.\n\n        ``404``\n            Requested resource does not exist.\n\n        ``500``\n            Mission parsing or another error has occurred.\n\n    Authorization\n        Required if configured.\n\n\n``POST /missions/\u003cpath\u003e``\n    Upload mission and properties to a given directory in storage.\n\n    Parameters\n        In URL\n            ``path``\n                Path to a directory relative to server's ``Missions``\n                directory. ``Missions`` root directory is used if ``path`` is\n                not specified.\n\n                Type\n                    ``string``\n\n                Example\n                    ``/missions/Net/dogfight``\n\n        In body\n            Mission and properties are passed as parts of\n            ``multipart/form-data`` request. Name of form fields does not\n            matter. Amount of files being uploaded is not limited.\n\n            Request body example:\n                .. code-block::\n\n                    POST /missions/Net/dogfight/dev HTTP/1.1\n                    Host: 127.0.0.1:5000\n                    Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW\n\n                    ------WebKitFormBoundary7MA4YWxkTrZu0gW\n                    Content-Disposition: form-data; name=\"file\"; filename=\"demo_sample.mis\"\n                    Content-Type:\n\n\n                    ------WebKitFormBoundary7MA4YWxkTrZu0gW\n                    Content-Disposition: form-data; name=\"props\"; filename=\"demo_sample_ru.properties\"\n                    Content-Type:\n\n\n                    ------WebKitFormBoundary7MA4YWxkTrZu0gW--\n\n    Responses\n        ``200``\n            Empty dictionary.\n\n            Example\n                .. code-block:: json\n\n                    {}\n\n    Side effects\n        - Target directory is created if it does not exist.\n        - Files are overwritten if they are already exist.\n\n    Authorization\n        Required if configured.\n\n\n``DELETE /missions/\u003cpath\u003e``\n    Delete mission with its property files from storage.\n\n    Parameters\n        In URL\n            ``path``\n                Path to a mission relative to server's ``Missions`` directory.\n\n                Type\n                    ``string``\n\n                Example\n                    ``/missions/Net/dogfight/demo_sample.mis``\n\n    Responses\n        ``200``\n            Empty dictionary.\n\n            Example\n                .. code-block:: json\n\n                    {}\n\n        ``404``\n            Requested mission does not exist.\n\n    Side effects\n        ``.property`` files which are associated with a given mission are also\n        deleted if present.\n\n    Authorization\n        Required if configured.\n\n\n``GET /missions/current/info``\n    Get information about current mission. Wraps ``mission`` console command.\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            Serialized `il2fb.ds.middleware.console.structures.MissionInfo \u003chttps://github.com/IL2HorusTeam/il2fb-ds-middleware/blob/master/il2fb/ds/middleware/console/structures.py#L154\u003e`_\n            structure.\n\n            Example\n                .. code-block:: json\n\n                    {\n                        \"status\": {\n                            \"name\": \"not_loaded\"\n                        },\n                        \"file_path\": null,\n                        \"__type__\": \"il2fb.ds.middleware.console.structures.MissionInfo\"\n                    }\n\n    Authorization\n        Required if configured.\n\n\n``POST /missions/\u003cpath\u003e/load``\n    Load a given mission to make it current. Wraps ``mission LOAD`` console\n    command.\n\n    Parameters\n        In URL\n            ``path``\n                Path to a mission relative to server's ``Missions`` directory.\n\n                Type\n                    ``string``\n\n                Example\n                    ``/missions/Net/dogfight/demo_sample.mis/load``\n\n    Responses\n        ``200``\n            Empty dictionary.\n\n            Example\n                .. code-block:: json\n\n                    {}\n\n    Authorization\n        Required if configured.\n\n\n``POST /missions/current/begin``\n    Begin current mission. Wraps ``mission BEGIN`` console command.\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            Empty dictionary.\n\n            Example\n                .. code-block:: json\n\n                    {}\n\n    Authorization\n        Required if configured.\n\n\n``POST /missions/current/end``\n    End current mission. Wraps ``mission END`` console command.\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            Empty dictionary.\n\n            Example\n                .. code-block:: json\n\n                    {}\n\n    Authorization\n        Required if configured.\n\n\n``POST /missions/current/unload``\n    Unload current mission. Wraps ``mission DESTROY`` console command.\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            Empty dictionary.\n\n            Example\n                .. code-block:: json\n\n                    {}\n\n    Authorization\n        Required if configured.\n\n\n``GET /radar/ships``\n    Get positions of all ships (moving and stationary).\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            List of `il2fb.ds.middleware.device_link.structures.ShipPosition \u003chttps://github.com/IL2HorusTeam/il2fb-ds-middleware/blob/master/il2fb/ds/middleware/device_link/structures.py#L57\u003e`_\n            structures.\n\n            Example\n                .. code-block:: json\n\n                    [\n                        {\n                            \"index\": 0,\n                            \"id\": \"0_Chief\",\n                            \"pos\": {\n                                \"x\": 8445,\n                                \"y\": 138394\n                            },\n                            \"is_stationary\": false,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                        },\n                        {\n                            \"index\": 1,\n                            \"id\": \"1_Chief\",\n                            \"pos\": {\n                                \"x\": 37758,\n                                \"y\": 225193\n                            },\n                            \"is_stationary\": false,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                        },\n                        {\n                            \"index\": 2,\n                            \"id\": \"8_Chief\",\n                            \"pos\": {\n                                \"x\": 29003,\n                                \"y\": 152135\n                            },\n                            \"is_stationary\": false,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                        },\n                        {\n                            \"index\": 3,\n                            \"id\": \"70_Static\",\n                            \"pos\": {\n                                \"x\": 43387,\n                                \"y\": 154521\n                            },\n                            \"is_stationary\": true,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                        },\n                        {\n                            \"index\": 4,\n                            \"id\": \"72_Static\",\n                            \"pos\": {\n                                \"x\": 43448,\n                                \"y\": 152697\n                            },\n                            \"is_stationary\": true,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                        }\n                    ]\n\n    Authorization\n        Required if configured.\n\n\n``GET /radar/ships/moving``\n    Get positions of moving ships.\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            List of `il2fb.ds.middleware.device_link.structures.ShipPosition \u003chttps://github.com/IL2HorusTeam/il2fb-ds-middleware/blob/master/il2fb/ds/middleware/device_link/structures.py#L57\u003e`_\n            structures.\n\n            Example\n                .. code-block:: json\n\n                    [\n                        {\n                            \"index\": 0,\n                            \"id\": \"0_Chief\",\n                            \"pos\": {\n                                \"x\": 8341,\n                                \"y\": 138642\n                            },\n                            \"is_stationary\": false,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                        },\n                        {\n                            \"index\": 1,\n                            \"id\": \"1_Chief\",\n                            \"pos\": {\n                                \"x\": 37510,\n                                \"y\": 224931\n                            },\n                            \"is_stationary\": false,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                        },\n                        {\n                            \"index\": 2,\n                            \"id\": \"8_Chief\",\n                            \"pos\": {\n                                \"x\": 28869,\n                                \"y\": 152486\n                            },\n                            \"is_stationary\": false,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                        }\n                    ]\n\n    Authorization\n        Required if configured.\n\n``GET /radar/ships/stationary``\n    Get positions of stationary ships.\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            List of `il2fb.ds.middleware.device_link.structures.ShipPosition \u003chttps://github.com/IL2HorusTeam/il2fb-ds-middleware/blob/master/il2fb/ds/middleware/device_link/structures.py#L57\u003e`_\n            structures.\n\n            Example\n                .. code-block:: json\n\n                    [\n                        {\n                            \"index\": 3,\n                            \"id\": \"70_Static\",\n                            \"pos\": {\n                                \"x\": 43387,\n                                \"y\": 154521\n                            },\n                            \"is_stationary\": true,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                        },\n                        {\n                            \"index\": 4,\n                            \"id\": \"72_Static\",\n                            \"pos\": {\n                                \"x\": 43448,\n                                \"y\": 152697\n                            },\n                            \"is_stationary\": true,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                        }\n                    ]\n\n    Authorization\n        Required if configured.\n\n\n``GET /radar/aircrafts/moving``\n    Get positions of moving aircrafts (controlled by users or AI).\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            List of `il2fb.ds.middleware.device_link.structures.MovingAircraftPosition \u003chttps://github.com/IL2HorusTeam/il2fb-ds-middleware/blob/master/il2fb/ds/middleware/device_link/structures.py#L23\u003e`_\n            structures.\n\n            Example\n                .. code-block:: json\n\n                    [\n                        {\n                            \"index\": 0,\n                            \"id\": \"I_JG100\",\n                            \"pos\": {\n                                \"x\": 80396,\n                                \"y\": 168150,\n                                \"z\": 1511\n                            },\n                            \"is_human\": false,\n                            \"member_index\": 0,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                        },\n                        {\n                            \"index\": 1,\n                            \"id\": \"I_JG100\",\n                            \"pos\": {\n                                \"x\": 80329,\n                                \"y\": 168158,\n                                \"z\": 1510\n                            },\n                            \"is_human\": false,\n                            \"member_index\": 1,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                        },\n                        {\n                            \"index\": 2,\n                            \"id\": \"g0101\",\n                            \"pos\": {\n                                \"x\": 66378,\n                                \"y\": 160822,\n                                \"z\": 1512\n                            },\n                            \"is_human\": false,\n                            \"member_index\": 0,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                        },\n                        {\n                            \"index\": 3,\n                            \"id\": \"g0101\",\n                            \"pos\": {\n                                \"x\": 66307,\n                                \"y\": 160823,\n                                \"z\": 1510\n                            },\n                            \"is_human\": false,\n                            \"member_index\": 1,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                        },\n                        {\n                            \"index\": 4,\n                            \"id\": \"john.doe\",\n                            \"pos\": {\n                                \"x\": 110695,\n                                \"y\": 202555,\n                                \"z\": 11\n                            },\n                            \"is_human\": true,\n                            \"member_index\": null,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                        }\n                    ]\n\n    Authorization\n        Required if configured.\n\n\n``GET /radar/ground-units/moving``\n    Get positions of moving ground units.\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            List of `il2fb.ds.middleware.device_link.structures.MovingGroundUnitPosition \u003chttps://github.com/IL2HorusTeam/il2fb-ds-middleware/blob/master/il2fb/ds/middleware/device_link/structures.py#L41\u003e`_\n            structures.\n\n            Example\n                .. code-block:: json\n\n                    [\n                        {\n                            \"index\": 0,\n                            \"id\": \"2_Chief\",\n                            \"member_index\": 0,\n                            \"pos\": {\n                                \"x\": 99673,\n                                \"y\": 202473,\n                                \"z\": 43\n                            },\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingGroundUnitPosition\"\n                        },\n                        {\n                            \"index\": 1,\n                            \"id\": \"4_Chief\",\n                            \"member_index\": 0,\n                            \"pos\": {\n                                \"x\": 163918,\n                                \"y\": 204481,\n                                \"z\": 15\n                            },\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingGroundUnitPosition\"\n                        },\n                        {\n                            \"index\": 2,\n                            \"id\": \"4_Chief\",\n                            \"member_index\": 1,\n                            \"pos\": {\n                                \"x\": 163928,\n                                \"y\": 204471,\n                                \"z\": 14\n                            },\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingGroundUnitPosition\"\n                        }\n                    ]\n\n    Authorization\n        Required if configured.\n\n\n``GET /radar/moving``\n    Get positions of all moving actors (aircrafts, ground units and moving\n    ships).\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            Serialized structure `il2fb.ds.airbridge.radar.AllMovingActorsPositions \u003chttps://github.com/IL2HorusTeam/il2fb-ds-airbridge/blob/master/il2fb/ds/airbridge/radar.py#L24\u003e`_.\n\n            Example\n                .. code-block:: json\n\n                    {\n                        \"aircrafts\": [\n                            {\n                                \"index\": 0,\n                                \"id\": \"I_JG100\",\n                                \"pos\": {\n                                    \"x\": 82480,\n                                    \"y\": 161721,\n                                    \"z\": 1861\n                                },\n                                \"is_human\": false,\n                                \"member_index\": 0,\n                                \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                            },\n                            {\n                                \"index\": 1,\n                                \"id\": \"john.doe\",\n                                \"pos\": {\n                                    \"x\": 110695,\n                                    \"y\": 202554,\n                                    \"z\": 11\n                                },\n                                \"is_human\": true,\n                                \"member_index\": null,\n                                \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                            }\n                        ],\n                        \"ground_units\": [\n                            {\n                                \"index\": 0,\n                                \"id\": \"2_Chief\",\n                                \"member_index\": 0,\n                                \"pos\": {\n                                    \"x\": 99903,\n                                    \"y\": 203297,\n                                    \"z\": 41\n                                },\n                                \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingGroundUnitPosition\"\n                            },\n                            {\n                                \"index\": 1,\n                                \"id\": \"3_Chief\",\n                                \"member_index\": 0,\n                                \"pos\": {\n                                    \"x\": 88322,\n                                    \"y\": 184137,\n                                    \"z\": 1\n                                },\n                                \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingGroundUnitPosition\"\n                            }\n                        ],\n                        \"ships\": [\n                            {\n                                \"index\": 0,\n                                \"id\": \"0_Chief\",\n                                \"pos\": {\n                                    \"x\": 7720,\n                                    \"y\": 140132\n                                },\n                                \"is_stationary\": false,\n                                \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                            },\n                            {\n                                \"index\": 1,\n                                \"id\": \"1_Chief\",\n                                \"pos\": {\n                                    \"x\": 35568,\n                                    \"y\": 222874\n                                },\n                                \"is_stationary\": false,\n                                \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                            }\n                        ],\n                        \"__type__\": \"il2fb.ds.airbridge.radar.AllMovingActorsPositions\"\n                    }\n\n    Authorization\n        Required if configured.\n\n\n``GET /radar/houses``\n    Get positions of houses.\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            List of `il2fb.ds.middleware.device_link.structures.HousePosition \u003chttps://github.com/IL2HorusTeam/il2fb-ds-middleware/blob/master/il2fb/ds/middleware/device_link/structures.py#L82\u003e`_\n            structures.\n\n            Example\n                .. code-block:: json\n\n                    [\n                        {\n                            \"index\": 0,\n                            \"id\": \"0_bld\",\n                            \"pos\": {\n                                \"x\": 100184,\n                                \"y\": 167170\n                            },\n                            \"status\": {\n                                \"name\": \"alive\",\n                                \"value\": \"A\"\n                            },\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.HousePosition\"\n                        },\n                        {\n                            \"index\": 1,\n                            \"id\": \"1_bld\",\n                            \"pos\": {\n                                \"x\": 100174,\n                                \"y\": 167142\n                            },\n                            \"status\": {\n                                \"name\": \"alive\",\n                                \"value\": \"A\"\n                            },\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.HousePosition\"\n                        }\n                    ]\n\n    Authorization\n        Required if configured.\n\n\n``GET /radar/stationary-objects``\n    Get positions of stationary objects.\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            List of `il2fb.ds.middleware.device_link.structures.StationaryObjectPosition \u003chttps://github.com/IL2HorusTeam/il2fb-ds-middleware/blob/master/il2fb/ds/middleware/device_link/structures.py#L73\u003e`_\n            structures.\n\n            Example\n                .. code-block:: json\n\n                    [\n                        {\n                            \"index\": 0,\n                            \"id\": \"0_Static\",\n                            \"pos\": {\n                                \"x\": 71906,\n                                \"y\": 178119,\n                                \"z\": 1\n                            },\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.StationaryObjectPosition\"\n                        },\n                        {\n                            \"index\": 1,\n                            \"id\": \"1_Static\",\n                            \"pos\": {\n                                \"x\": 71616,\n                                \"y\": 176956,\n                                \"z\": 1\n                            },\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.StationaryObjectPosition\"\n                        }\n                    ]\n\n    Authorization\n        Required if configured.\n\n\n``GET /radar/stationary``\n    Get positions of all stationary actors (stationary objects, houses and\n    stationary ships).\n\n    Parameters\n        No parameters.\n\n    Responses\n        ``200``\n            Serialized structure `il2fb.ds.airbridge.radar.AllStationaryActorsPositions \u003chttps://github.com/IL2HorusTeam/il2fb-ds-airbridge/blob/master/il2fb/ds/airbridge/radar.py#L38\u003e`_.\n\n            Example\n                .. code-block:: json\n\n                    {\n                        \"stationary_objects\": [\n                            {\n                                \"index\": 0,\n                                \"id\": \"0_Static\",\n                                \"pos\": {\n                                    \"x\": 71906,\n                                    \"y\": 178119,\n                                    \"z\": 1\n                                },\n                                \"__type__\": \"il2fb.ds.middleware.device_link.structures.StationaryObjectPosition\"\n                            },\n                            {\n                                \"index\": 1,\n                                \"id\": \"1_Static\",\n                                \"pos\": {\n                                    \"x\": 71616,\n                                    \"y\": 176956,\n                                    \"z\": 1\n                                },\n                                \"__type__\": \"il2fb.ds.middleware.device_link.structures.StationaryObjectPosition\"\n                            }\n                        ],\n                        \"houses\": [\n                            {\n                                \"index\": 0,\n                                \"id\": \"0_bld\",\n                                \"pos\": {\n                                    \"x\": 100184,\n                                    \"y\": 167170\n                                },\n                                \"status\": {\n                                    \"name\": \"alive\",\n                                    \"value\": \"A\"\n                                },\n                                \"__type__\": \"il2fb.ds.middleware.device_link.structures.HousePosition\"\n                            },\n                            {\n                                \"index\": 1,\n                                \"id\": \"1_bld\",\n                                \"pos\": {\n                                    \"x\": 100174,\n                                    \"y\": 167142\n                                },\n                                \"status\": {\n                                    \"name\": \"alive\",\n                                    \"value\": \"A\"\n                                },\n                                \"__type__\": \"il2fb.ds.middleware.device_link.structures.HousePosition\"\n                            }\n                        ],\n                        \"ships\": [\n                            {\n                                \"index\": 3,\n                                \"id\": \"70_Static\",\n                                \"pos\": {\n                                    \"x\": 43387,\n                                    \"y\": 154521\n                                },\n                                \"is_stationary\": true,\n                                \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                            },\n                            {\n                                \"index\": 4,\n                                \"id\": \"72_Static\",\n                                \"pos\": {\n                                    \"x\": 43448,\n                                    \"y\": 152697\n                                },\n                                \"is_stationary\": true,\n                                \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                            }\n                        ],\n                        \"__type__\": \"il2fb.ds.airbridge.radar.AllStationaryActorsPositions\"\n                    }\n\n    Authorization\n        Required if configured.\n\n\nNATS\n~~~~\n\nAirbridge provides requests API over NATS by using it's\n`request-reply \u003chttp://nats.io/documentation/concepts/nats-req-rep/\u003e`_\nmechanism.\n\nAll messages are formatted as JSON just like in case of REST.\n\nEach request message defines its operation by ``opcode`` parameter of\n``integer`` type.\n\nThose requests, which accept arguments, specify ``payload`` parameter as\ndictionary.\n\nOptional ``timeout`` argument is also available for all requests. As in case\nof REST API, this parameter has type ``float`` and is measured in seconds, for\nexample:\n\n.. code-block:: json\n\n    {\n        \"opcode\": 0,\n        \"payload\": {\n            \"timeout\": 5\n        }\n    }\n\nEvery response contains ``status``. It is an integer representation of request\nexecution status, where ``0`` stands for success and ``1`` — for failure.\nExample:\n\n.. code-block:: json\n\n    {\n        \"status\": 0\n    }\n\n\nAvailable NATS requests are listed below along with examples of responses.\n\n\n``GET_SERVER_INFO``\n    Get information about server. Wraps ``server`` console command.\n\n    Opcode\n        ``0``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 0\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": {\n                    \"type\": \"Local server\",\n                    \"name\": \"Development server\",\n                    \"description\": \"Dedicated Server for local tests\",\n                    \"__type__\": \"il2fb.ds.middleware.console.structures.ServerInfo\"\n                }\n            }\n\n\n``GET_HUMANS_LIST``\n    Get list of users connected to server. Wraps ``user`` console command.\n\n    Opcode\n        ``10``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 10\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": [\n                    {\n                        \"callsign\": \"john.doe\",\n                        \"ping\": 61,\n                        \"score\": 0,\n                        \"belligerent\": {\n                            \"name\": \"none\",\n                            \"value\": 0,\n                            \"verbose_name\": \"none\",\n                            \"help_text\": null,\n                        },\n                        \"aircraft\": null,\n                        \"__type__\": \"il2fb.ds.middleware.console.structures.Human\"\n                    }\n                ]\n            }\n\n\n``GET_HUMANS_COUNT``\n    Get number of users connected to server. Equals to a number of records\n    returned by ``user`` console command.\n\n    Opcode\n        ``11``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 11\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": 7\n            }\n\n\n``GET_HUMANS_STATISTICS``\n    Get server's statistics for users connected to server.\n    Wraps ``user STAT`` console command.\n\n    Opcode\n        ``12``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 12\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": [\n                    {\n                        \"callsign\": \"john.doe\",\n                        \"score\": 0,\n                        \"state\": \"Selects Aircraft\",\n                        \"enemy_aircraft_kills\": 0,\n                        \"enemy_static_aircraft_kills\": 0,\n                        \"enemy_tank_kills\": 0,\n                        \"enemy_car_kills\": 0,\n                        \"enemy_artillery_kills\": 0,\n                        \"enemy_aaa_kills\": 0,\n                        \"enemy_wagon_kills\": 0,\n                        \"enemy_ship_kills\": 0,\n                        \"enemy_radio_kills\": 0,\n                        \"friendly_aircraft_kills\": 0,\n                        \"friendly_static_aircraft_kills\": 0,\n                        \"friendly_tank_kills\": 0,\n                        \"friendly_car_kills\": 0,\n                        \"friendly_artillery_kills\": 0,\n                        \"friendly_aaa_kills\": 0,\n                        \"friendly_wagon_kills\": 0,\n                        \"friendly_ship_kills\": 0,\n                        \"friendly_radio_kills\": 0,\n                        \"bullets_fired\": 0,\n                        \"bullets_hit\": 0,\n                        \"bullets_hit_air_targets\": 0,\n                        \"rockets_launched\": 0,\n                        \"rockets_hit\": 0,\n                        \"bombs_dropped\": 0,\n                        \"bombs_hit\": 0,\n                        \"__type__\": \"il2fb.ds.middleware.console.structures.HumanStatistics\"\n                    }\n                ]\n            }\n\n\n``KICK_ALL_HUMANS``\n    Kick all users from server.\n\n    Opcode\n        ``20``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 20\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": 0\n            }\n\n\n``KICK_HUMAN_BY_CALLSIGN``\n    Kick user from server by user's callsign.\n\n    Opcode\n        ``21``\n\n    Parameters\n        ``callsign``\n            Callsign of user to kick.\n\n            Type\n                ``string``\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 21,\n                \"payload\": {\n                    \"callsign\": \"john.doe\"\n                }\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": null\n            }\n\n\n``CHAT_TO_ALL``\n    Send message in chat to everyone.\n\n    Opcode\n        ``30``\n\n    Parameters\n        ``message``\n            Message to send.\n\n            Type\n                ``string``\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 30,\n                \"payload\": {\n                    \"message\": \"hello!\"\n                }\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": null\n            }\n\n\n``CHAT_TO_HUMAN``\n    Send message in chat to a user.\n\n    Opcode\n        ``31``\n\n    Parameters\n        ``message``\n            Message to send.\n\n            Type\n                ``string``\n\n        ``addressee``\n            Callsign of user to chat to.\n\n            Type\n                ``string``\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 31,\n                \"payload\": {\n                    \"message\": \"hello!\",\n                    \"addressee\": \"john.doe\"\n                }\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": null\n            }\n\n\n``CHAT_TO_BELLIGERENT``\n    Send message in chat to a belligerent (army).\n\n    Opcode\n        ``32``\n\n    Parameters\n        ``message``\n            Message to send.\n\n            Type\n                ``string``\n\n        ``addressee``\n            Callsign of belligerent to chat to. See `il2fb.commons.organization.Belligerents \u003chttps://github.com/IL2HorusTeam/il2fb-commons/blob/master/il2fb/commons/organization.py#L20\u003e`_\n            for details.\n\n            Type\n                ``integer``\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 32,\n                \"payload\": {\n                    \"message\": \"hello!\",\n                    \"addressee\": 1\n                }\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": null\n            }\n\n\n``GET_MISSION_INFO``\n    Get information about current mission. Wraps ``mission`` console command.\n\n    Opcode\n        ``40``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 40\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": {\n                    \"status\": {\n                        \"name\": \"not_loaded\"\n                    },\n                    \"file_path\": null,\n                    \"__type__\": \"il2fb.ds.middleware.console.structures.MissionInfo\"\n                }\n            }\n\n\n``LOAD_MISSION``\n    Load a given mission to make it current. Wraps ``mission LOAD`` console\n    command.\n\n    Opcode\n        ``41``\n\n    Parameters\n        ``file_path``\n            Path to a mission relative to server's ``Missions`` directory.\n\n            Type\n                ``string``\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 41,\n                \"payload\": {\n                    \"file_path\": \"Net/dogfight/demo_sample.mis\"\n                }\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": null\n            }\n\n\n``BEGIN_MISSION``\n    Begin current mission. Wraps ``mission BEGIN`` console command.\n\n    Opcode\n        ``42``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 42\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": null\n            }\n\n\n``END_MISSION``\n    End current mission. Wraps ``mission END`` console command.\n\n    Opcode\n        ``43``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 43\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": null\n            }\n\n\n``UNLOAD_MISSION``\n    Unload current mission. Wraps ``mission DESTROY`` console command.\n\n    Opcode\n        ``44``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 44\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": null\n            }\n\n\n``GET_ALL_SHIPS_POSITIONS``\n    Get positions of all ships (moving and stationary).\n\n    Opcode\n        ``50``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 50\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": [\n                    {\n                        \"index\": 0,\n                        \"id\": \"0_Chief\",\n                        \"pos\": {\n                            \"x\": 8445,\n                            \"y\": 138394\n                        },\n                        \"is_stationary\": false,\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                    },\n                    {\n                        \"index\": 1,\n                        \"id\": \"1_Chief\",\n                        \"pos\": {\n                            \"x\": 37758,\n                            \"y\": 225193\n                        },\n                        \"is_stationary\": false,\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                    },\n                    {\n                        \"index\": 2,\n                        \"id\": \"8_Chief\",\n                        \"pos\": {\n                            \"x\": 29003,\n                            \"y\": 152135\n                        },\n                        \"is_stationary\": false,\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                    },\n                    {\n                        \"index\": 3,\n                        \"id\": \"70_Static\",\n                        \"pos\": {\n                            \"x\": 43387,\n                            \"y\": 154521\n                        },\n                        \"is_stationary\": true,\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                    },\n                    {\n                        \"index\": 4,\n                        \"id\": \"72_Static\",\n                        \"pos\": {\n                            \"x\": 43448,\n                            \"y\": 152697\n                        },\n                        \"is_stationary\": true,\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                    }\n                ]\n            }\n\n\n``GET_MOVING_SHIPS_POSITIONS``\n    Get positions of moving ships.\n\n    Opcode\n        ``51``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 51\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": [\n                    {\n                        \"index\": 0,\n                        \"id\": \"0_Chief\",\n                        \"pos\": {\n                            \"x\": 8445,\n                            \"y\": 138394\n                        },\n                        \"is_stationary\": false,\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                    },\n                    {\n                        \"index\": 1,\n                        \"id\": \"1_Chief\",\n                        \"pos\": {\n                            \"x\": 37758,\n                            \"y\": 225193\n                        },\n                        \"is_stationary\": false,\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                    },\n                    {\n                        \"index\": 2,\n                        \"id\": \"8_Chief\",\n                        \"pos\": {\n                            \"x\": 29003,\n                            \"y\": 152135\n                        },\n                        \"is_stationary\": false,\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                    }\n                ]\n            }\n\n\n``GET_STATIONARY_SHIPS_POSITIONS``\n    Get positions of stationary ships.\n\n    Opcode\n        ``52``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 52\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": [\n                    {\n                        \"index\": 3,\n                        \"id\": \"70_Static\",\n                        \"pos\": {\n                            \"x\": 43387,\n                            \"y\": 154521\n                        },\n                        \"is_stationary\": true,\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                    },\n                    {\n                        \"index\": 4,\n                        \"id\": \"72_Static\",\n                        \"pos\": {\n                            \"x\": 43448,\n                            \"y\": 152697\n                        },\n                        \"is_stationary\": true,\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                    }\n                ]\n            }\n\n\n``GET_MOVING_AIRCRAFTS_POSITIONS``\n    Get positions of moving aircrafts (controlled by users or AI).\n\n    Opcode\n        ``53``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 53\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": [\n                    {\n                        \"index\": 0,\n                        \"id\": \"I_JG100\",\n                        \"pos\": {\n                            \"x\": 80396,\n                            \"y\": 168150,\n                            \"z\": 1511\n                        },\n                        \"is_human\": false,\n                        \"member_index\": 0,\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                    },\n                    {\n                        \"index\": 1,\n                        \"id\": \"I_JG100\",\n                        \"pos\": {\n                            \"x\": 80329,\n                            \"y\": 168158,\n                            \"z\": 1510\n                        },\n                        \"is_human\": false,\n                        \"member_index\": 1,\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                    },\n                    {\n                        \"index\": 2,\n                        \"id\": \"g0101\",\n                        \"pos\": {\n                            \"x\": 66378,\n                            \"y\": 160822,\n                            \"z\": 1512\n                        },\n                        \"is_human\": false,\n                        \"member_index\": 0,\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                    },\n                    {\n                        \"index\": 3,\n                        \"id\": \"g0101\",\n                        \"pos\": {\n                            \"x\": 66307,\n                            \"y\": 160823,\n                            \"z\": 1510\n                        },\n                        \"is_human\": false,\n                        \"member_index\": 1,\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                    },\n                    {\n                        \"index\": 4,\n                        \"id\": \"john.doe\",\n                        \"pos\": {\n                            \"x\": 110695,\n                            \"y\": 202555,\n                            \"z\": 11\n                        },\n                        \"is_human\": true,\n                        \"member_index\": null,\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                    }\n                ]\n            }\n\n\n``GET_MOVING_GROUND_UNITS_POSITIONS``\n    Get positions of moving ground units.\n\n    Opcode\n        ``54``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 54\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": [\n                    {\n                        \"index\": 0,\n                        \"id\": \"2_Chief\",\n                        \"member_index\": 0,\n                        \"pos\": {\n                            \"x\": 99673,\n                            \"y\": 202473,\n                            \"z\": 43\n                        },\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingGroundUnitPosition\"\n                    },\n                    {\n                        \"index\": 1,\n                        \"id\": \"4_Chief\",\n                        \"member_index\": 0,\n                        \"pos\": {\n                            \"x\": 163918,\n                            \"y\": 204481,\n                            \"z\": 15\n                        },\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingGroundUnitPosition\"\n                    },\n                    {\n                        \"index\": 2,\n                        \"id\": \"4_Chief\",\n                        \"member_index\": 1,\n                        \"pos\": {\n                            \"x\": 163928,\n                            \"y\": 204471,\n                            \"z\": 14\n                        },\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingGroundUnitPosition\"\n                    }\n                ]\n            }\n\n\n``GET_ALL_MOVING_ACTORS_POSITIONS``\n    Get positions of all moving actors (aircrafts, ground units and moving\n    ships).\n\n    Opcode\n        ``55``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 55\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": {\n                    \"aircrafts\": [\n                        {\n                            \"index\": 0,\n                            \"id\": \"I_JG100\",\n                            \"pos\": {\n                                \"x\": 82480,\n                                \"y\": 161721,\n                                \"z\": 1861\n                            },\n                            \"is_human\": false,\n                            \"member_index\": 0,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                        },\n                        {\n                            \"index\": 1,\n                            \"id\": \"john.doe\",\n                            \"pos\": {\n                                \"x\": 110695,\n                                \"y\": 202554,\n                                \"z\": 11\n                            },\n                            \"is_human\": true,\n                            \"member_index\": null,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                        }\n                    ],\n                    \"ground_units\": [\n                        {\n                            \"index\": 0,\n                            \"id\": \"2_Chief\",\n                            \"member_index\": 0,\n                            \"pos\": {\n                                \"x\": 99903,\n                                \"y\": 203297,\n                                \"z\": 41\n                            },\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingGroundUnitPosition\"\n                        },\n                        {\n                            \"index\": 1,\n                            \"id\": \"3_Chief\",\n                            \"member_index\": 0,\n                            \"pos\": {\n                                \"x\": 88322,\n                                \"y\": 184137,\n                                \"z\": 1\n                            },\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingGroundUnitPosition\"\n                        }\n                    ],\n                    \"ships\": [\n                        {\n                            \"index\": 0,\n                            \"id\": \"0_Chief\",\n                            \"pos\": {\n                                \"x\": 7720,\n                                \"y\": 140132\n                            },\n                            \"is_stationary\": false,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                        },\n                        {\n                            \"index\": 1,\n                            \"id\": \"1_Chief\",\n                            \"pos\": {\n                                \"x\": 35568,\n                                \"y\": 222874\n                            },\n                            \"is_stationary\": false,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                        }\n                    ],\n                    \"__type__\": \"il2fb.ds.airbridge.radar.AllMovingActorsPositions\"\n                }\n            }\n\n\n``GET_ALL_HOUSES_POSITIONS``\n    Get positions of houses.\n\n    Opcode\n        ``56``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 56\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": [\n                    {\n                        \"index\": 0,\n                        \"id\": \"0_bld\",\n                        \"pos\": {\n                            \"x\": 100184,\n                            \"y\": 167170\n                        },\n                        \"status\": {\n                            \"name\": \"alive\",\n                            \"value\": \"A\"\n                        },\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.HousePosition\"\n                    },\n                    {\n                        \"index\": 1,\n                        \"id\": \"1_bld\",\n                        \"pos\": {\n                            \"x\": 100174,\n                            \"y\": 167142\n                        },\n                        \"status\": {\n                            \"name\": \"alive\",\n                            \"value\": \"A\"\n                        },\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.HousePosition\"\n                    }\n                ]\n            }\n\n\n``GET_STATIONARY_OBJECTS_POSITIONS``\n    Get positions of stationary objects.\n\n    Opcode\n        ``57``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 57\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": [\n                    {\n                        \"index\": 0,\n                        \"id\": \"0_Static\",\n                        \"pos\": {\n                            \"x\": 71906,\n                            \"y\": 178119,\n                            \"z\": 1\n                        },\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.StationaryObjectPosition\"\n                    },\n                    {\n                        \"index\": 1,\n                        \"id\": \"1_Static\",\n                        \"pos\": {\n                            \"x\": 71616,\n                            \"y\": 176956,\n                            \"z\": 1\n                        },\n                        \"__type__\": \"il2fb.ds.middleware.device_link.structures.StationaryObjectPosition\"\n                    }\n                ]\n            }\n\n\n``GET_ALL_STATIONARY_ACTORS_POSITIONS``\n    Get positions of all stationary actors (stationary objects, houses and\n    stationary ships).\n\n    Opcode\n        ``58``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 58\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0,\n                \"payload\": {\n                    \"stationary_objects\": [\n                        {\n                            \"index\": 0,\n                            \"id\": \"0_Static\",\n                            \"pos\": {\n                                \"x\": 71906,\n                                \"y\": 178119,\n                                \"z\": 1\n                            },\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.StationaryObjectPosition\"\n                        },\n                        {\n                            \"index\": 1,\n                            \"id\": \"1_Static\",\n                            \"pos\": {\n                                \"x\": 71616,\n                                \"y\": 176956,\n                                \"z\": 1\n                            },\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.StationaryObjectPosition\"\n                        }\n                    ],\n                    \"houses\": [\n                        {\n                            \"index\": 0,\n                            \"id\": \"0_bld\",\n                            \"pos\": {\n                                \"x\": 100184,\n                                \"y\": 167170\n                            },\n                            \"status\": {\n                                \"name\": \"alive\",\n                                \"value\": \"A\"\n                            },\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.HousePosition\"\n                        },\n                        {\n                            \"index\": 1,\n                            \"id\": \"1_bld\",\n                            \"pos\": {\n                                \"x\": 100174,\n                                \"y\": 167142\n                            },\n                            \"status\": {\n                                \"name\": \"alive\",\n                                \"value\": \"A\"\n                            },\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.HousePosition\"\n                        }\n                    ],\n                    \"ships\": [\n                        {\n                            \"index\": 3,\n                            \"id\": \"70_Static\",\n                            \"pos\": {\n                                \"x\": 43387,\n                                \"y\": 154521\n                            },\n                            \"is_stationary\": true,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                        },\n                        {\n                            \"index\": 4,\n                            \"id\": \"72_Static\",\n                            \"pos\": {\n                                \"x\": 43448,\n                                \"y\": 152697\n                            },\n                            \"is_stationary\": true,\n                            \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                        }\n                    ],\n                    \"__type__\": \"il2fb.ds.airbridge.radar.AllStationaryActorsPositions\"\n                }\n            }\n\n\nStreaming\n---------\n\nAs it was stated earlier, Airbridge provides multiple streaming facilities.\nThis means that it's possible to subscribe to a stream of events which\noriginate from different sources. The following sources are provided:\n\n#. ``chat`` — messages coming from chat. This includes messages from server and\n   system.\n#. ``events`` — events coming from game log and user-connection events coming\n   from server's console;\n#. ``not parsed strings`` — strings coming from game log which were not parsed\n   due some error;\n#. ``radar`` — coordinates of all moving actors which are queried periodically\n   and period is specified for each subscriber separatelly. Default refresh\n   period is ``5 sec``.\n\nStreaming facilities allow subscription of any object which conforms to\n`StreamingSubscriber \u003chttps://github.com/IL2HorusTeam/il2fb-ds-airbridge/blob/master/il2fb/ds/airbridge/streaming/subscribers/base.py#L8\u003e`_\ninterface.\n\nThose subscribers which conform to `PluggableStreamingSubscriber \u003chttps://github.com/IL2HorusTeam/il2fb-ds-airbridge/blob/master/il2fb/ds/airbridge/streaming/subscribers/base.py#L15\u003e`_\ninterface, can be created automatically at startup of application.\n`TextFileStreamingSink \u003chttps://github.com/IL2HorusTeam/il2fb-ds-airbridge/blob/master/il2fb/ds/airbridge/streaming/subscribers/file.py#L11\u003e`_,\n`JSONFileStreamingSink \u003chttps://github.com/IL2HorusTeam/il2fb-ds-airbridge/blob/master/il2fb/ds/airbridge/streaming/subscribers/file.py#L51\u003e`_\nand `NATSStreamingSink \u003chttps://github.com/IL2HorusTeam/il2fb-ds-airbridge/blob/master/il2fb/ds/airbridge/streaming/subscribers/nats.py#L17\u003e`_\nare examples of pluggable subscribers. Configuration of such subscribers is\nexplained in \"Configuration\" section.\n\nAll streaming data is transmitted as message which are formatted as JSON\nstrings. Each message contains a ``timestamp`` which indicates time when event\nwas detected and ``data`` which contains event-related data.\n\n..\n\n    **NOTE**: event's timestamp indicates time when event was detected, not\n    the time when it has occured. Usually these times are equal, but there may\n    be a slight difference, for example, for game log events: game log is\n    monitored by polling file with a specific period and events may occur\n    before log watcher will notice them. Moreover, game server may write\n    messages to game log with delay. So, it's better to extract event's time\n    from event's data if it is present and to use ``timestamp`` field as event\n    identifier.\n\nExamples of messages from different streaming facilities are given below.\n\nMessage from ``chat`` stream:\n\n.. code-block:: json\n\n    {\n        \"timestamp\": \"2017-11-25T13:22:42.145599\",\n        \"data\": {\n            \"body\": \"john.doe joins the game.\",\n            \"actor\": null,\n            \"from_human\": false,\n            \"from_server\": false,\n            \"from_system\": true,\n            \"__type__\": \"il2fb.ds.middleware.console.events.ChatMessageWasReceived\"\n        }\n    }\n\nMessage from ``events`` stream:\n\n.. code-block:: json\n\n    {\n        \"timestamp\": \"2017-11-25T15:22:45.211668\",\n        \"data\": {\n            \"time\": \"15:22:44\",\n            \"actor\": {\n                \"flight\": \"g0101\",\n                \"aircraft\": 3\n            },\n            \"pos\": {\n                \"x\": 55079.348,\n                \"y\": 175689.23\n            },\n            \"__type__\": \"il2fb.parsers.game_log.events.AIAircraftHasDespawned\"\n        }\n    }\n\nMessage from ``not parsed strings`` stream:\n\n.. code-block:: json\n\n    {\n        \"timestamp\": \"2017-11-25T15:19:33.754441\",\n        \"data\": {\n            \"value\": \"[3:19:33 PM] 3do/Tree/Line/live.sim destroyed by 8_Chief at 69716.7 158365.38\",\n            \"__type__\": \"il2fb.ds.airbridge.dedicated_server.game_log.NotParsedGameLogString\"\n        }\n    }\n\nMessage from ``radar`` stream:\n\n.. code-block:: json\n\n    {\n        \"timestamp\": \"2017-11-25T15:50:51.689771\",\n        \"data\": {\n            \"aircrafts\": [\n                {\n                    \"index\": 0,\n                    \"id\": \"I_JG100\",\n                    \"pos\": {\n                        \"x\": 82480,\n                        \"y\": 161721,\n                        \"z\": 1861\n                    },\n                    \"is_human\": false,\n                    \"member_index\": 0,\n                    \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                },\n                {\n                    \"index\": 1,\n                    \"id\": \"john.doe\",\n                    \"pos\": {\n                        \"x\": 110695,\n                        \"y\": 202554,\n                        \"z\": 11\n                    },\n                    \"is_human\": true,\n                    \"member_index\": null,\n                    \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingAircraftPosition\"\n                }\n            ],\n            \"ground_units\": [\n                {\n                    \"index\": 0,\n                    \"id\": \"2_Chief\",\n                    \"member_index\": 0,\n                    \"pos\": {\n                        \"x\": 99903,\n                        \"y\": 203297,\n                        \"z\": 41\n                    },\n                    \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingGroundUnitPosition\"\n                },\n                {\n                    \"index\": 1,\n                    \"id\": \"3_Chief\",\n                    \"member_index\": 0,\n                    \"pos\": {\n                        \"x\": 88322,\n                        \"y\": 184137,\n                        \"z\": 1\n                    },\n                    \"__type__\": \"il2fb.ds.middleware.device_link.structures.MovingGroundUnitPosition\"\n                }\n            ],\n            \"ships\": [\n                {\n                    \"index\": 0,\n                    \"id\": \"0_Chief\",\n                    \"pos\": {\n                        \"x\": 7720,\n                        \"y\": 140132\n                    },\n                    \"is_stationary\": false,\n                    \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                },\n                {\n                    \"index\": 1,\n                    \"id\": \"1_Chief\",\n                    \"pos\": {\n                        \"x\": 35568,\n                        \"y\": 222874\n                    },\n                    \"is_stationary\": false,\n                    \"__type__\": \"il2fb.ds.middleware.device_link.structures.ShipPosition\"\n                }\n            ],\n            \"__type__\": \"il2fb.ds.airbridge.radar.AllMovingActorsPositions\"\n        }\n    }\n\nThe subsections below describe different subscribers which can be used as\nstreaming destination.\n\n\nFiles\n~~~~~\n\nAirbridge supports streaming of data to local files. In this case every single\nline in text file will contain a message serialized as a single JSON string.\n\nThis is the simplest and the fastest streaming subscriber, however it is\nlimited to local file system of server.\n\nEvents from different streaming facilities must go to different output files.\n\nStreaming to files can be configured to run from start of application.\n\nRefer to \"Configuration\" section for examples and details.\n\n\nNATS\n~~~~\n\nStreaming to NATS channels allows Airbridge to send data to remote storage.\n\nThis is one of the key functionalities of Airbridge, as it allows to escape\nserver's file system and operating system at all. This also makes it possible\nfor multiple remote consumers to subscribe to events in different combinations.\n\nAlso NATS streaming server allows to configure persistence of messages, so they\ncan be accessed and processed in future.\n\nEach streaming facility can publish messages to its own channel (subject).\nPublishing all messages to a single channel is also possible if needed.\n\nStreaming to NATS channels can be configured to run from start of application.\n\nRefer to \"Configuration\" section for examples and details.\n\n\nWebSockets\n~~~~~~~~~~\n\nAirbridge allows its clients to subscribe to streaming facilities via\nWebSockets.\n\nThis means that web application can show data in real time in browser. Such\nfeature can be used for building admin dashboards for Airbridge. It's not\nrecommended to use this API for displaying data to end users in production, as\nthis can affect overall performance of Airbridge.\n\nTo start any subscription, a client must connect to streaming endpoint via\nweb-socket. This is done by sending ``HTTP GET`` request to ``/streaming``\nroute, e.g.:\n\n::\n\n    GET ws://127.0.0.1:5000/streaming\n\nAfter connection is established, the client can send messages to server to\nsubscribe to or unsubscribe from a specific streaming facility.\n\nLike in case of NATS requests API, each request to WS streaming subscription\nAPI is specified by operation code ``opcode``. Responses have similar structure\nas well: every response contains integer ``status`` field, where ``0`` stands\nfor success and ``1`` — for failure.\n\nSubscription requests are described below.\n\n\n``SUBSCRIBE_TO_CHAT``\n    Subscribe to ``chat`` stream.\n\n    Opcode\n        ``0``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 0\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0\n            }\n\n\n``UNSUBSCRIBE_FROM_CHAT``\n    Unsubscribe from ``chat`` stream.\n\n    Opcode\n        ``1``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 1\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0\n            }\n\n\n``SUBSCRIBE_TO_EVENTS``\n    Subscribe to ``events`` stream.\n\n    Opcode\n        ``10``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 10\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0\n            }\n\n\n``UNSUBSCRIBE_FROM_EVENTS``\n    Unsubscribe from ``events`` stream.\n\n    Opcode\n        ``11``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 11\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0\n            }\n\n\n``SUBSCRIBE_TO_NOT_PARSED_STRINGS``\n    Subscribe to ``not parsed strings`` stream.\n\n    Opcode\n        ``20``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 20\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0\n            }\n\n\n``UNSUBSCRIBE_FROM_NOT_PARSED_STRINGS``\n    Unsubscribe from ``not parsed strings`` stream.\n\n    Opcode\n        ``21``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 21\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0\n            }\n\n\n``SUBSCRIBE_TO_RADAR``\n    Subscribe to ``radar`` stream.\n\n    Opcode\n        ``30``\n\n    Parameters\n        ``refresh_period``\n            Refresh period of radar for current subscriber. Measured in\n            seconds. The parameter is optional.\n\n            Type\n                ``float``\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 30,\n                \"payload\": {\n                    \"refresh_period\": 30\n                }\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0\n            }\n\n\n``UNSUBSCRIBE_FROM_RADAR``\n    Unsubscribe from ``radar`` stream.\n\n    Opcode\n        ``31``\n\n    Parameters\n        No parameters.\n\n    Request example\n        .. code-block:: json\n\n            {\n                \"opcode\": 31\n            }\n\n    Response example:\n        .. code-block:: json\n\n            {\n                \"status\": 0\n            }\n\n\nReleases\n========\n\nInformation about project's releases can be found at\n`releases page \u003chttps://github.com/IL2HorusTeam/il2fb-ds-airbridge/releases\u003e`_.\n\nEach release includes release notes, precompiled binaries and sources.\n\n\nInstallation\n============\n\nThis section describes possible ways to install Airbridge application.\nThe easiest way is to install from binary which is described below.\n\n\nFrom binary\n-----------\n\nAirbridge comes with precompiled executable binaries which are available at\nreleases page (see the section above). Installation is simple and it is done\njust by unpacking executable file from release archive which is suitable for\ntarget operating system.\n\n\nFrom PyPI\n---------\n\nIt's also possible to get Airbridge as Python package from PyPI\n(Python Package Index). It is available as `il2fb-ds-airbridge \u003chttps://pypi.python.org/pypi?name=il2fb-ds-airbridge\u0026:action=display\u003e`_\npackage and can be installed via ``pip``:\n\n.. code-block:: bash\n\n    pip install il2fb-ds-airbridge\n\nSame via ``easy_install``:\n\n.. code-block:: bash\n\n    easy_install il2fb-ds-airbridge\n\n..\n\n    **NOTE**: Airbridge is implemented using Python 3.6, so at least this\n    version must be used to run the application.\n\n\nFrom sources\n------------\n\nIf neither precompiled version nor package are suitable or\ndebugging/development is needed, then Airbridge can be installed from local\nsources.\n\nSources can be obtained by cloning Git repository or by downloading them from\nreleases page.\n\nUsual installation can be done by executing setup script:\n\n.. code-block:: bash\n\n    python ./setup.py install\n\nIt is also possible to install application as editable package, so that changes\nin source code will be applied immediately:\n\n.. code-block:: bash\n\n    pip install -e .\n\n\nManual compilation\n------------------\n\nTo compile binary from source one will need to use `PyInstaller \u003chttp://www.pyinstaller.org\u003e`_.\n\nIts ``spec`` file is defined as ``airbridge.spec`` at the root of source\ndirectory. This makes compilation to be very simple:\n\n.. code-block:: bash\n\n    pyinstaller airbridge.spec -y --clean\n\nPyInstaller will create a binary executable inside ``dist`` directory.\n\n..\n\n    **NOTE**: all dependencies must be installed locally to make it possible to\n    compile a single binary file. Dependencies for Windows are defined at\n    ``requirements/dist-windows.txt`` and dependencies for other platforms are\n    defined at ``requirements/dist.txt``.\n\n\nConfiguration\n=============\n\nThis section describes how Airbridge can be configured.\n\nAirbridge application requires a configuration file to operate. This\nrequirement comes out of application's nature: it is a wrapper of dedicated\nserver, so it needs to know at least were server's executable file is located.\n\nApplication's configuration has hierarchical structure and is stored as a YAML\nfile. The following subsections describe different aspects of configuration.\n\nFull example of configuration file `can be found in examples directory \u003chttps://github.com/IL2HorusTeam/il2fb-ds-airbridge/tree/master/examples\u003e`_.\n\n\nLogging\n-------\n\nLogging is critical for detection and localization of issues and errors. As\nerrors can occur at any stage of application execution, it is important to\nconfigure it in the first place.\n\nAirbridge produces 2 log files: a main log file which records application's\nexecution flow and a separate file for dumping tracebacks of exceptions.\n\nLet's take a look at configuration of logging which is used by default:\n\n.. code-block:: yaml\n\n    logging:\n      files:\n        main:\n          level: debug\n          file_path: airbridge.log\n          keep_after_restart: yes\n          is_delayed: no\n        exceptions:\n          file_path: airbridge.exc\n          keep_after_restart: yes\n          is_delayed: no\n      rotation:\n          is_enabled: yes\n          max_size: 10485760\n          max_backups: 10\n      trace: no\n      encoding: utf8\n      use_local_time: no\n\n\nFiles\n~~~~~\n\n``files`` section defines options for two log files. The options are the same\nfor both of them, except ``level`` option which can be specified only for\n``main`` file. Description of all options is given below.\n\n``level``\n    Logging level for ``main`` file. Can be one of: ``debug``, ``info``,\n    ``warning``, ``error`` or ``critical``.\n\n    Logging level for ``exceptions`` file is always set to ``debug``, so that\n    tracebacks from any level can be captured. Usually tracebacks are logged\n    with log message of ``error`` level, however they are not limited to it.\n    For example, warning messages also can include tracebacks.\n\n``file_path``\n    Path to a file where log will be stored.\n\n``keep_after_restart``\n    Tells whether existing log file should be retained after restart of\n    application or a clean one should be created.\n\n``is_delayed``\n    Tells whether file should be created only after a first message is written\n    to it or it should be created immediately after start of application.\n\n\nRotation\n~~~~~~~~\n\nRotation of log files allows to keep their size under acceptable limit. After\nfile size reaches this limit it is backed up and new empty log file is created.\n\nBy default rotation is enabled and size limit for a single file is set to\n10'485'760 bytes (10 MiB). This feature can be disabled and external tools\nlike `logrotate \u003chttps://linux.die.net/man/8/logrotate\u003e`_ can be used instead.\n\n``is_enabled``\n    Tells whether rotation is turned on.\n\n``max_size``\n    Size limit for a single file.\n\n``max_backups``\n    Number of backups which are stored in file system before application will\n    start to delete old backups. For example, if ``max_backups`` is set to 10\n    and there are already 10 backups exist, then when file size of log reaches\n    its ``max_size`` limit, the oldest existing backup will be erased and a new\n    one will be created.\n\n\nOther options\n~~~~~~~~~~~~~\n\nOther available logging options are listed below.\n\n``trace``\n    Tells whether tracing level of logging is enabled. Tracing messages are\n    logged w","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fil2horusteam%2Fil2fb-ds-airbridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fil2horusteam%2Fil2fb-ds-airbridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fil2horusteam%2Fil2fb-ds-airbridge/lists"}