Skip to content
ugcs-SDK edited this page Nov 11, 2016 · 31 revisions

Overview

UgCS .Net SDK gives access to core services of our Universal Control Server. Using this SDK it is possible to develop third party client applications that can programmatically:

  • .access various UgCS entities like missions, routes, vehicles, vehicle profiles, payloads, telemetry, etc;
  • .subscribe to notifications like telemetry, vehicle connection, routes change, ads-b collision, etc;
  • .issue commands to vehicles;
  • .calculate routes;
  • .access elevation data.

SDK gives developer a way to implement a simple widget to display telemetry parameter or full functional drone control client application.

Release history

SDK version Date Description
2.9 2016/05/01 First public BETA compatible with UgCS 2.9
2.10 2016/10/14 SDK version with updated protobuf version

Place of .Net SDK in UgCS architecture

TODO

  • -.architecture
  • -.differences between One/Open/Pro

Prerequisites

Visual Studio 2013 Community Edition

.Net Framework 3.5 or later

Nuget package manager (shall be a part of Visual Studio)

Installed UgCS application, 2.10 or later

Note : number of allowed UgCS client connections to UGCS Server depends on the license type. For Open and One versions only one connection allowed. For Pro 3 and Enterprise is unlimeted. This means that for Open and One it is not possible to have UgCS standard client and your application running at the same time.

Getting started

Creating project

Open Visual Studio and select on of possible C# projects. To use SDK you have to add references to appropriate assemblies. The most recent assemblies are available in our nugget repository. To get package open your package manager command line and type: nuget install ugcs-dotnet-sdk

After successful download the following references shall appear in your project:

  • -.Sdk.dll
  • -.Protobuf-net.dll

We use protobuf as a container for our messages so SDK uses it as a dependency.

Add the following namespaces to your "using" sections of C# code:

using UGCS.Sdk.Protocol;
using UGCS.Sdk.Protocol.Encoding;
using UGCS.Sdk.Tasks;
using ProtoBuf; 

Basic concepts

There are two ways of communication between client application and UGCS Server:

  • -.asynchronous request/ response;
  • -.subscription.

Though all communication is asynchronous there are certain ways to implement synchronous workflow on the client.

Typically you will use requests/responses to make standard CRUD operations and to list objects. For example get list of vehicles, create vehicle profile, remove payload, etc.

Subscriptions are useful to listen for some events. For example if you want to get telemetry stream for the vehicle you typically subscribe to telemetry events. It is more appropriate way comparing to setting timer on the client and pulling UCS every N seconds.

Connecting to UGCS Server

Establishing connection to UGCS Server is the first step to be performed. It consists of the following main operations:

  1. establishing TCP connection;
  2. authorizing client session

Create instance of TcpClient class and pass host and port as parameters. If UgCS Server is running on the same computer then specify "localhost" for a host and 3334 as a port number.

TcpClient tcpClient = new TcpClient("localhost", 3334);
MessageSender messageSender = new MessageSender(tcpClient.Session);            
MessageReceiver messageReceiver = new MessageReceiver(tcpClient.Session);           
MessageExecutor messageExecutor = new MessageExecutor(messageSender, messageReceiver, new InstantTaskScheduler());
messageExecutor.Configuration.DefaultTimeout = 10000;

To test your application you need UgCS Server running. Check that clicking UgCS icon in tray.

Compile and run that simple application. If client object instantiated successfully than you may find your session object in client.Session property.

The next step is to get clientID. ClientID is a thing that you must specify for every request towards UgCS Server. But before that we need to prepare some code for sending and receiving messages.

AuthorizeHciRequest request = new AuthorizeHciRequest();
AuthorizeHciRequest request = new AuthorizeHciRequest();
request.ClientId = -1;
request.Locale = "en-US";
var future = messageExecutor.Submit<AuthorizeHciResponse>(request);
future.Wait();
AuthorizeHciResponse AuthorizeHciResponse = future.Value;
int clientId = AuthorizeHciResponse.ClientId;

What we do here is just sending AuthorizeHciRequest to UgCS Server. Request has to parameters:

  • -.ClientID and we set it to default -1 value;
  • -.Locale – client locale (optional), en-US by default here. Local defines localization for strings that UgCS Server sends to client.

Another important thing to note is how we get response from the UgCS Server. We employ future (or promise) concept here for asynchronous communication. Typically this means that you submit some response , specify callback and do not wait for response doing something. But here we explicitly wait for response invoking Value property of authFuture object. That is a general approach for making pseudo-synchronous requests/responses.

We are almost ready to do something really useful. The only thing that has to be done is to login into the system. UgCS Server uses login based authentication model. Look at the source code:

LoginRequest loginRequest = new LoginRequest();
loginRequest.UserLogin = "admin";
loginRequest.UserPassword = "admin";
loginRequest.ClientId = clientId;
LoginResponse LoginResponce = messageExecutor.Submit<LoginResponse>(loginRequest).Value;

It is pretty straightforward. Note that we use clientID as an argument to LoginRequest. The only question is how to deal with login and password. Generally you must specify login and password from user list. But there is a trick. If you have only one user registered then you can put empty strings and SDK will try to make autologin.

That's it. Now we are logged in into UGCS server and can do something.

Accessing server objects

Vehicles

List

This example shows how to get vehicle list from the server. First of all we need find appropriate request/response pair. There is a universal operation for getting object lists called GetObjectList. It works similar for many objects. You need to specify clientId and ObjectType. In our case object type I "Vehicle"

GetObjectListRequest request = new GetObjectListRequest()
{
    ClientId = clientId,
    ObjectType = "Vehicle",
    RefreshDependencies = true
};
request.RefreshExcludes.Add("Avatar");
request.RefreshExcludes.Add("PayloadProfile");
request.RefreshExcludes.Add("Route");
var task = messageExecutor.Submit<GetObjectListResponse>(request);

Nothing new in this sample. And we did a half of the job. Now we need to access vehicle data itself. Response object contains a lot of general properties and some specific ones. Actual data resides in Objects collection. So to list vehicles we can use the following code:

var list = task.Value;
foreach (var vehicle in list.Objects)
{
    Console.WriteLine(string.Format("name: {0}; id: {1}; type: {2}",
           vehicle.Vehicle.Name, vehicle.Vehicle.Id, vehicle.Vehicle.Type.ToString()));
}
Vehicle vehicle = task.Value.Objects.FirstOrDefault().Vehicle;

Update

This example shows how to update vehicle on the server.

CreateOrUpdateObjectRequest request = new CreateOrUpdateObjectRequest()
{
    ClientId = clientId,
    Object = new DomainObjectWrapper().Put(vehicle, "Vehicle"),
    WithComposites = true,
    ObjectType = "Vehicle",
    AcquireLock = false
};
var task = messageExecutor.Submit<CreateOrUpdateObjectResponse>(request);

Delete

This example shows how to delete vehicle on the server.

DeleteObjectRequest request = new DeleteObjectRequest()
{
    ClientId = clientId,
    ObjectId = vehicle.Id,
    ObjectType = "Vehicle"
};
var task = messageExecutor.Submit<DeleteObjectResponse>(request);

Vehicle profiles

List

MessageFuture<GetObjectListResponse> listFuture =
    messageExecutor.Submit<GetObjectListResponse>(
    new GetObjectListRequest
    {
        ClientId = clientId,
        ObjectType = "VehicleProfile"
    });
GetObjectListResponse listResp = listFuture.Value;

Response object contains data in Objects property. Each object is of DomainObjectWrapper type. Wrapper has a lot of properties for different object types. In this case we need VehicleProfile property. Each profile stores it's parameters in Parameters collection.

Payloads

List

MessageFuture<GetObjectListResponse> listFuture =    messageExecutor.Submit<GetObjectListResponse>(
    new GetObjectListRequest
    {
        ClientId = clientId,
        ObjectType = "PayloadProfile"
    });
GetObjectListResponse listResp = listFuture.Value;

Response object contains data in Objects property. Each object is of DomainObjectWrapper type. Wrapper has a lot of properties for different object types. In this case we need PayloadProfile property. Each profile stores it's parameters in Parameters collection.

Missions

Create mission

Mission mission = new Mission
{
    CreationTime = 1270011748,
    Name = "Mission name",
    Owner = user
};
CreateOrUpdateObjectRequest request = new CreateOrUpdateObjectRequest()
{
    ClientId = 1,
    Object = new DomainObjectWrapper().Put(mission, "Mission"),
    WithComposites = true,
    ObjectType = "Mission",
    AcquireLock = false
};
var task = messageExecutor.Submit<CreateOrUpdateObjectResponse>(request);

No-Fly Zones

Accessing telemetry storage

Here is a sample of telemetry request to obtain telemetry for the last hour. Not that we specify vehicle object (see Vehicles sample) as a parameter. Another important parameters are ToTime and FromTime – time interval. Limit defines maximum number of telemetry records to be fetched. Zero means no limit.

MessageFuture<GetTelemetryResponse> telemetryFuture = messageExecutor.Submit<GetTelemetryResponse>(new GetTelemetryRequest
{
    ClientId = clientId,
    Vehicle = vehicle,
    ToTime = DateTimeUtilities.ToPosixMilliseconds(DateTime.Now),
    FromTime = DateTimeUtilities.ToPosixMilliseconds(
         DateTime.Now.Subtract(new TimeSpan(1, 0, 0))),
    Limit = 0,
    LimitSpecified = true,
    ToTimeSpecified = true
});
GetTelemetryResponse telemetryResp = telemetryFuture.Value;

Response object contains data in Telemetry property. Each object is of TelemetryDto type. Field "Type" contains field type, "Value" contains value and "Time" is a POSIX time.

The following types available:

Type Description
TT_BATTERY_VOLTAGE
TT_ROLL Roll
TT_PITCH Pitch
TT_YAW Yaw
TT_ROLL_SPEED
TT_PITCH_SPEED
TT_YAW_SPEED
TT_LATITUDE Latitude from autopilot (filtered)
TT_LONGITUDE Longitude from autopilot (filtered)
TT_MSL_ALTITUDE AMSL Altitude
TT_AGL_ALTITUDE AGL altitude
TT_GROUND_SPEED_X Ground speed X part (filtered)
TT_GROUND_SPEED_Y Ground speed Y part (filtered)
TT_GROUND_SPEED_Z Ground speed Z part (filtered)
TT_LATITUDE_GPS Latitude raw
TT_LONGITUDE_GPS Longitude raw
TT_ALTITUDE_GPS
TT_GROUND_SPEED_GPS
TT_ACCELERATION_X_RAW
TT_ACCELERATION_Y_RAW
TT_ACCELERATION_Z_RAW
TT_ANGULAR_SPEED_X_RAW
TT_ANGULAR_SPEED_Y_RAW
TT_ANGULAR_SPEED_Z_RAW
TT_MAGNETIC_X_RAW
TT_MAGNETIC_Y_RAW
TT_MAGNETIC_Z_RAW
TT_ABSOLUTE_PRESSURE
TT_DIFFERENTIAL_PRESSURE
TT_TEMPERATURE
TT_AIR_SPEED
TT_GROUND_SPEED Ground speed (vector sum of X and Y) ??
TT_HEADING Heading
TT_THROTTLE
TT_CLIMB_RATE Vertical speed
TT_GPS_SATELLITES_VISIBLE
TT_ROUTE_MILAGE
TT_TELEMETRY_DROP_RATE
TT_DOWNLINK_CONNECTED
TT_UPLINK_CONNECTED
TT_CONTROL_MODE
TT_STATE
TT_COURSE
TT_RELATIVE_ALTITUDE
TT_ELEVATION Ground elevation
TT_PAYLOAD_1_ROLL
TT_PAYLOAD_1_TILT
TT_PAYLOAD_1_YAW
TT_CAMERA_1_FOV_HORIZONTAL
TT_CAMERA_1_FOV_VERTICAL
TT_GPS_FIX_TYPE
TT_RC_LINK_QUALITY
TT_ADSB_TRANSPONDER_MODE
TT_ADSB_IDENT_STATE
TT_ADSB_SQUAWK_CODE
TT_ADSB_ALTITUDE_SOURCE
TT_ADSB_ALTITUDE
TT_ADSB_ERROR_FLAGS
TT_PAYLOAD_2_ROLL
TT_PAYLOAD_2_TILT
TT_PAYLOAD_2_YAW
TT_CAMERA_2_FOV_HORIZONTAL
TT_CAMERA_2_FOV_VERTICAL
TT_PAYLOAD_1_CONTROL_MODE
TT_PAYLOAD_2_CONTROL_MODE
TT_PAYLOAD_1_AVAILABLE
TT_PAYLOAD_2_AVAILABLE
TT_PAYLOAD_1_POWERED
TT_PAYLOAD_2_POWERED
TT_CAMERA_1_ZOOM
TT_CAMERA_2_ZOOM
TT_CAMERA_1_RECORDING
TT_CAMERA_2_RECORDING
TT_CAMERA_1_IMAGE_COUNT
TT_CAMERA_2_IMAGE_COUNT
TT_CAMERA_1_IMAGE_CAPACITY
TT_CAMERA_2_IMAGE_CAPACITY
TT_CAMERA_1_VIDEO_COUNT
TT_CAMERA_2_VIDEO_COUNT

One more important things to note is that in the sample above we use Posix time. In the future releases of SDK we will include these functions in our SDK. But you can use the following code instead for now:

public static readonly DateTime PosixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

public static long ToPosixMilliseconds(this DateTime localTime)
{
   DateTime utcTime = localTime.ToUniversalTime();
   TimeSpan span = utcTime — PosixEpoch;
   return (long)span.TotalMilliseconds;
}

public static DateTime FromPosixMilliseconds(long milliseconds)
{
   TimeSpan span = TimeSpan.FromMilliseconds(milliseconds);
   return (PosixEpoch + span).ToLocalTime();
}

Note : telemetry recording is disabled in UgCS for Emulator by default. For development purposes is convenient to switch it on. To do that open <UgCS Installation Dir>\Server\ucs\ucs.properties and change field ucs.emulator.storeTelemetry= true.

Subscriptions

Vehicle subscription.

Code below initiates vehicle subscription.

ObjectModificationSubscription _objectNotificationSubscription;
    _eventSubscriptionWrapper.ObjectModificationSubscription = _objectNotificationSubscription;
SubscribeEventRequest requestEvent = new SubscribeEventRequest();
requestEvent.ClientId = clientId;
requestEvent.Subscription = _eventSubscriptionWrapper; //Subscription Wrapper
var responce = _connect.Executor.Submit<SubscribeEventResponse>(requestEvent);
var subscribeEventResponse = responce.Value;
SubscriptionToken st = new SubscriptionToken(subscribeEventResponse.SubscriptionId, _getObjectNotificationHandler<Vehicle>(
    (token, exception, vehicle) =>
    {
        //Recieve modificated vehcile object
    }
), _eventSubscriptionWrapper);
tokens.Add(st);    

Telemetry subscription.

Code describes how to subscribe telemetry

SubscribeEventRequest requestEvent = new SubscribeEventRequest();
requestEvent.ClientId = _connect.AuthorizeHciResponse.ClientId;
requestEvent.Subscription = _eventSubscriptionWrapper;
var responce = _connect.Executor.Submit<SubscribeEventResponse>(requestEvent);
var subscribeEventResponse = responce.Value;
SubscriptionToken st = new SubscriptionToken(subscribeEventResponse.SubscriptionId,              _getTelemetryNotificationHandler(
    (vehicleId, telemetry) =>
    {
        //Place where recieve telemetry.
    }
), _eventSubscriptionWrapper);

//NotificationListener object
_notificationListener.AddSubscription(st); 

Working with routes

Create new route

Route route = new Route
{
    CreationTime = 123456789,
    Name = "Route name",
    Mission = mission
};
ChangeRouteVehicleProfileRequest request = new ChangeRouteVehicleProfileRequest
{
    ClientId = 1,
    Route = route,
    NewProfile = new VehicleProfile { Id = 1 }
};
MessageFuture<ChangeRouteVehicleProfileResponse> future = Executor.Submit<ChangeRouteVehicleProfileResponse>(request);

future.Wait();
route = future.Value.Route;
route.HomeLocationSource = HomeLocationSource.HLS_FIRST_WAYPOINT;
route.TrajectoryType = TrajectoryType.TT_STAIR;
route.AltitudeType = AltitudeType.AT_AGL;
route.MaxAltitude = 50.0;
route.SafeAltitude = 3.0;
route.CheckAerodromeNfz = false;
route.CheckAerodromeNfzSpecified = true;
route.InitialSpeed = 0.0;
route.MaxSpeed = 0.0;
route.CheckCustomNfz = false;
route.CheckCustomNfzSpecified = true;
route.Failsafes.Add(new Failsafe()
{
    Action = FailsafeAction.FA_GO_HOME,
    ActionSpecified = true,
    Reason = FailsafeReason.FR_RC_LOST,
    ReasonSpecified = true
});
route.Failsafes.Add(new Failsafe()
{
    Action = FailsafeAction.FA_LAND,
    ActionSpecified = true,
    Reason = FailsafeReason.FR_LOW_BATTERY,
    ReasonSpecified = true
});
route.Failsafes.Add(new Failsafe()
{
    Action = FailsafeAction.FA_WAIT,
    ActionSpecified = true,
    Reason = FailsafeReason.FR_GPS_LOST,
    ReasonSpecified = true
});
route.Failsafes.Add(new Failsafe()
{
    Action = FailsafeAction.FA_GO_HOME,
    ActionSpecified = true,
    Reason = FailsafeReason.FR_DATALINK_LOST,
    ReasonSpecified = true
});
CreateOrUpdateObjectRequest request = new CreateOrUpdateObjectRequest()
{
    ClientId = clientId,
    Object = new DomainObjectWrapper().Put(route, "Route"),
    WithComposites = true,
    ObjectType = "Route",
    AcquireLock = false
};
var task = messageExecutor.Submit<CreateOrUpdateObjectResponse>(request);

Add waypoint to route

SegmentDefinition newSegment = new SegmentDefinition
{
    Uuid = Guid.NewGuid().ToString(),
    AlgorithmClassName = "com.ugcs.ucs.service.routing.impl.WaypointAlgorithm"
};
newSegment.Figure = new Figure { Type = FigureType.FT_POINT };
newSegment.ParameterValues.Add(new ParameterValue()
{
    Name = "speed",
    Value = "5.0",
    ValueSpecified = true
});
newSegment.ParameterValues.Add(new ParameterValue()
{
    Name = "wpTurnType",
    Value = "SPLINE",
    ValueSpecified = true
});
newSegment.ParameterValues.Add(new ParameterValue()
{
    Name = "avoidObstacles",
    Value = "True",
    ValueSpecified = true
});
newSegment.ParameterValues.Add(new ParameterValue()
{
    Name = "avoidTerrain",
    Value = "True",
    ValueSpecified = true
});
newSegment.Figure.Points.Add(new FigurePoint()
{
    AglAltitude = 20,
    AglAltitudeSpecified = true,
    AltitudeType = AltitudeType.AT_AGL,
    AltitudeTypeSpecified = true,
    Latitude = 0.99443566874164979f,
    LatitudeSpecified = true,
    Longitude = 0.42015588448045021f,
    LongitudeSpecified = true,
    Order = 0,
    Wgs84Altitude = 0.0,
    Wgs84AltitudeSpecified = true
});
route.Segments.Insert(0, newSegment);

Calculating the route

Code below initiates roite calculation

var updatedRoute = GetUpdatedRouteById(routeId);
ProcessRouteRequest request = new ProcessRouteRequest
{
    ClientId = clientId,
    Route = route
};
MessageFuture<ProcessRouteResponse> task = messageExecutor.Submit<ProcessRouteResponse>(request);
task.Wait();
var processedRoute = task.Value.ProcessedRoute;

Uploading the route

Code below upload ProcessedRoute to selected vehicle

UploadRouteRequest request = new UploadRouteRequest
{
    ClientId = clientId,
    ProcessedRoute = route,
    Vehicle = vehicle,
};
MessageFuture<UploadRouteResponse> task = messageExecutor.Submit<UploadRouteResponse>(request);
task.Wait();

Getting/setting take-off point altitude

Set takeoff point is Vehicle field update request to the server. Code below updates fields list.

var fields = new string[] { "altitudeOrigin" });
UpdateObjectFieldsRequest request = new UpdateObjectFieldsRequest
{
    ClientId = clientId,
    ObjectType = "Vehicle",
    Object = new DomainObjectWrapper().Put(vehicle, "Vehicle"),
};
request.FieldNames.AddRange(fields);
var task = messageExecutor.Submit<UpdateObjectFieldsResponse>(request);
task.Wait();

Getting home position

Home location is availble from vehicle telemetry.

TT_HOME_LATITUDE
TT_HOME_LONGITUDE
TT_HOME_AMSL_ALTITUDE

Issuing command to a vehicle

Code below show how to send specific command to Vehicle

SendCommandRequest request = new SendCommandRequest
{
    ClientId = clientId,
    Command = new UGCS.Sdk.Protocol.Encoding.Command
    {
        Code = "CommandCode",
        Subsystem = Subsystem.S_FLIGHT_CONTROLLER,
    }
};
request.Vehicles.Add(new Vehicle() { Id = vehicle.Id });
var responce = messageExecutor.Submit<SendCommandResponse>(request);
responce.Wait();

Send command examples. Arm example:

SendCommandRequest request = new SendCommandRequest
{
     ClientId = 1,
     Command = new UGCS.Sdk.Protocol.Encoding.Command
     {
         Code = "arm",
         Subsystem = Subsystem.S_FLIGHT_CONTROLLER,
     }
};
request.Vehicles.Add(new Vehicle() { Id = 1 });

Takeoff command with argument:

SendCommandRequest request = new SendCommandRequest
{
    ClientId = _connect.AuthorizeHciResponse.ClientId,
    Command = new UGCS.Sdk.Protocol.Encoding.Command
    {
        Code = "takeoff_command",
        Subsystem = Subsystem.S_FLIGHT_CONTROLLER,
        Silent = true,
        ResultIndifferent = true
    }
};

request.Vehicles.Add(new Vehicle() { Id = 1 });
List<CommandArgument> list = new List<CommandArgument>();
list.Add(new CommandArgument { Code = "relativeAltitude", Value = new Value() { StringValue = Settings.Default.MinimumOperatingAltitude.ToString("0.00", System.Globalization.CultureInfo.InvariantCulture) }  });
request.Command.Arguments.AddRange(list);

References

Operation Messages Comments
Authorize client session AuthorizeHciRequest/Response
Login LoginRequest/Response
List objects GetObjectsListRequest/Response Works for different object types:
- Vehicle
- VehicleProfile
-…

Protobuf messages

message Wgs84LocationDto {
	required double latitude = 1;
	required double longitude = 2;
	required double altitude = 3;
	required AltitudeType altitudeType = 4; 
}

message MeasurePointDto {
	required double latitude = 1;
	required double longitude = 2;
	required double altitude = 3;
	required AltitudeType altitudeType = 4; 
	optional double angle = 5;
	optional double distance = 6; 
}

message PlaceDto {
	required Wgs84LocationDto location = 1;
	optional string displayName = 2;
	optional double rank = 3;
}

message VersionsInfoDto {
	repeated Version versions = 1;
	optional string releaseInfo = 2;
}

message StatisticsRecordDto {
	required string parameter = 1;
	required string value = 2;
}

message StatisticsDto {
	required int64 time = 1;
	required string clientUID = 2;
	required string clientMAC = 3;
	required string clientOsType = 4;
	required string clientOsVersion = 5;
	required string unityVersion = 6; 	
	repeated StatisticsRecordDto details = 7; 
}

message CommandSetDto {
	repeated string commandCode = 1;
}

enum DronesharePrivacy {
	DP_DEFAULT = 0;
	DP_PRIVATE = 1;
	DP_PUBLIC = 2;
	DP_SHARED = 3;
	DP_RESEARCHER = 4;
}

message LicensePermissionsDto {
	required string licenseName = 1;
	required int32 maxAuthenticatedHciSessions = 2;
	required bool multinode = 3;
	required bool kmlImport = 4;
	required bool demImport = 5;
	repeated PlatformAndDoublePairDto maxAglAltitude = 6;
	repeated PlatformAndDoublePairDto maxDistanceToHome = 7;
	repeated PlatformAndIntegerPairDto  maxBuildings = 8;
	repeated PlatformAndBooleanPairDto customNfz = 9;
	repeated PlatformAndBooleanPairDto airportNfzDisabling = 10;
	repeated PlatformAndBooleanPairDto adsbReceiver = 11;
	repeated PlatformAndBooleanPairDto videoRecording = 12;
	repeated PlatformAndBooleanPairDto cameraFootprint = 13;
	repeated PlatformAndBooleanPairDto adsbTransponder = 14;
}

message PlatformAndBooleanPairDto {
	required Platform platform = 1;
	required bool value = 2;
}

message PlatformAndIntegerPairDto {
	required Platform platform = 1;
	required int32 value = 2;
}

message PlatformAndDoublePairDto {
	required Platform platform = 1;
	required double value = 2;
}

message VehicleTargetLocationDto {
	required Vehicle vehicle = 1;
	required int64 sequenceId = 2;
	optional Wgs84LocationDto location = 3;
	optional double acceptanceRadius = 4;
}

message PlatformAndVehicleTypePairDto {
	required Platform platform = 1;
	required VehicleType vehicleType = 2;
}

message FailsafeReasonActionsDto {
	required FailsafeReason reason = 1;
	repeated FailsafeAction actions = 2;
}

message FailsafeActionsDto {
	required PlatformAndVehicleTypePairDto platformAndVehicleType = 1;
	repeated FailsafeReasonActionsDto failsafeReasonActions = 2;
}

message AlgorithmAndActionCodeDto {
	required TraverseAlgorithm algorithm= 1;
	repeated ActionCode actionCodes = 2;
}

message AlgorithmsDto {
	required PlatformAndVehicleTypePairDto platformAndVehicleType = 1;
	repeated AlgorithmAndActionCodeDto algorithmAndActionCodes = 2;
}

message ProgressDto {
	required string title = 1;
	required int32 progress = 2;
	required int32 maxProgress = 3;
}

// Messages ///////////////////////////////////////////////////////////////////

// Error 
message Error {
	optional string errorMessage = 1;
	optional int32 errorCode = 2;
}

message AuthorizeHciRequest {
	required int32 clientId = 1 [default = -1];
	optional string locale = 2;
}

message AuthorizeHciResponse {
	required int32 clientId = 1;
}

message SetHciLocaleRequest {
	required int32 clientId = 1;
	required string locale = 2;
}

message SetHciLocaleResponse {
}

message LoginRequest {
	required int32 clientId = 1;
	required string userLogin = 2;
	required string userPassword = 3;
}

message LoginResponse {
	required User user = 1;
}

message LogoutRequest {
	required int32 clientId = 1;
}

message LogoutResponse {
}

message ProcessRouteRequest {
	required int32 clientId = 1;
	required Route route = 2;
}

message ProcessRouteResponse {
	required Route route = 1;
}

message ConvertRouteAltitudesRequest {
	required int32 clientId = 1;
	required Route route = 2;
	required AltitudeType altitudeType = 4;
}

message ConvertRouteAltitudesResponse {
	required Route route = 1;
}

message ChangeRouteVehicleProfileRequest {
	required int32 clientId = 1;
	required Route route = 2;
	required VehicleProfile newProfile = 3;
}

message ChangeRouteVehicleProfileResponse {
	required Route route = 1;
	repeated string warningMessage = 2;
}

message GetParametersSelectionValuesRequest {
	required int32 clientId = 1;
	required Route route = 2;
	required TraverseAlgorithm algorithm = 3;
}

message GetParametersSelectionValuesResponse {
	repeated Selection selections = 1;
}

message GetElevationProfileRequest {
	required int32 clientId = 1;
	required double samplingStep = 3;
	repeated Wgs84LocationDto locations = 4;
	optional int32 number = 5;
}

message GetElevationProfileResponse {
	repeated Wgs84LocationDto locations = 1;
	repeated double elevations = 2;
	repeated double obstacleHeight = 3;
}

message CalculateSplineRequest {
	required int32 clientId = 1;
	repeated Waypoint waypounts = 2;
	optional double accuracy = 3;
}

message CalculateSplineResponse {
	repeated Wgs84LocationDto locations = 1;
}

// Transfer - Export / Import

message ExportRouteToXmlRequest {
	required int32 clientId = 1;
	required Route route = 2;
}

message ExportRouteToXmlResponse {
	required bytes routeXml = 1;
}

message ImportRouteFromXmlRequest {
	required int32 clientId = 1;
	required bytes routeXml = 2;
}

message ImportRouteFromXmlResponse {
	required Route route = 1;
}

message ExportMissionToXmlRequest {
	required int32 clientId = 1;
	required Mission mission = 2;
}

message ExportMissionToXmlResponse {
	required bytes missionXml = 1;
}

message ImportMissionFromXmlRequest {
	required int32 clientId = 1;
	required bytes missionXml = 2;
}

message ImportMissionFromXmlResponse {
	required Mission mission = 1;
}

message ExportTelemetryToXmlRequest {
	required int32 clientId = 1;
	required TelemetryInterval telemetryInterval = 2; 
}

message ExportTelemetryToXmlResponse {
	required bytes telemetryXml = 1;
}

message ImportTelemetryFromXmlRequest {
	required int32 clientId = 1;
	required bytes telemetryXml = 2;
	required ConflictResolutionMode conflictResolutionMode = 3;
}

message ImportTelemetryFromXmlResponse {
	required TelemetryInterval telemetryInterval = 1; 
}


// Measuring

message GetLineOfSightRequest {
	required int32 clientId = 1;
	required MeasurePointDto observerPosition = 2;
	required double maxDistance = 3;
	required int32 approxPointsNumber = 4;
}

message GetLineOfSightResponse {
	repeated MeasurePointDto points = 1;
}


// NFZ

message GetNfzListRequest {
	required int32 clientId = 1;
	required double minLatitude = 2;
	required double minLongitude = 3;
	required double maxLatitude = 4;
	required double maxLongitude = 5;
	optional bool refreshDependencies = 6 [default = false];
	repeated string refreshExcludes = 7;
}

message GetNfzListResponse {
	repeated NoFlightZone zones = 1;
}


// Models

message GetModelListRequest {
	required int32 clientId = 1;
	required double minLatitude = 2;
	required double minLongitude = 3;
	required double minAltitude = 4;
	required double maxLatitude = 5;
	required double maxLongitude = 6;
	required double maxAltitude = 7;
	optional bool refreshDependencies = 8 [default = false];
	repeated string refreshExcludes = 9;
}

message GetModelListResponse {
	repeated Model models = 1;
}

message GetRasterGridRequest {
	required int32 clientId = 1;
	required double minLatitude = 3;
	required double minLongitude = 4;
	required double maxLatitude = 5;
	required double maxLongitude = 6;
	required int32 width = 7;
	required int32 height = 8;
}

message GetRasterGridResponse {
	repeated float values = 1;
	required int32 width = 2;
	required int32 height = 3;
	required bool noData = 4;
}

message GetRasterValuesRequest {
	required int32 clientId = 1;
	repeated double latitudes = 3;
	repeated double longitudes = 4;
}

message GetRasterValuesResponse {
	repeated float values = 1;
	required bool noData = 2;
}

message GetTelemetryRequest {
	required int32 clientId = 1;
	required Vehicle vehicle = 2;
	required int64 fromTime = 3;
	optional int64 toTime = 4;
	optional int32 limit = 5 [default = 7200];
}

message GetTelemetryResponse {
	repeated TelemetryDto telemetry = 1;
	optional int64 nextTelemetryTime = 2;
}

message DeleteTelemetryRequest {
	required int32 clientId = 1;
	required Vehicle vehicle = 2;
	optional int64 fromTime = 3;
	optional int64 toTime = 4;
}

message DeleteTelemetryResponse {
}

message TraceTelemetryFramesRequest {
	required int32 clientId = 1;
	required Vehicle vehicle = 2;
	required int64 originTime = 3;
	required double interval = 4;
	required int32 number = 5;
}

message TraceTelemetryFramesResponse {
	repeated bool frames = 1;
	repeated CommandSetDto commandFrames = 2;
}

message CountTelemetryRequest {
	required int32 clientId = 1;
	required Vehicle vehicle = 2;
	optional int64 fromTime = 3;
	optional int64 toTime = 4;
	optional bool estimateTLogSize = 5 [default = false];
}

message CountTelemetryResponse {
	required int64 count = 1;
	optional int64 tLogSize = 2;
}

message GetKmlRouteRepresentationRequest {
	required int32 clientId = 1;
	required string routeName = 2;
	required VehicleProfile routeVehicleProfile = 3;
	repeated Wgs84LocationDto waypoints = 4;
}

message GetKmlRouteRepresentationResponse {
	required bytes kmlData = 1;
}

message GetAdsbAircraftListRequest {
	required int32 clientId = 1;
	required Wgs84LocationDto location = 2;
	required double radius = 3;
	required double height = 4;
}

message GetAdsbAircraftListResponse {
	repeated AdsbAircraft aircrafts = 1;
}

message SearchPlacesRequest {
	required int32 clientId = 1;
	required string query = 2;
	required int32 limit = 3 [default = 7];
}

message SearchPlacesResponse {
	repeated PlaceDto places = 1;
}

message GetVehicleLogRequest {
	required int32 clientId = 1;
	repeated Vehicle vehicles = 2;
	optional int32 limit = 3 [default = 15];
	optional SeverityLevel level = 4 [default = SL_INFORMATIONAL];
}

message GetVehicleLogResponse {
	repeated VehicleLogEntry vehicleLogEntries = 1;
}

message GetVehicleLogByTimeRangeRequest {
	required int32 clientId = 1;
	repeated Vehicle vehicles = 2;
	required int64 fromTime = 3;
	required int64 toTime = 4;
	optional SeverityLevel level = 5 [default = SL_INFORMATIONAL];
}

message GetVehicleLogByTimeRangeResponse {
	repeated VehicleLogEntry vehicleLogEntries = 1;
}

message SendCommandRequest {
	required int32 clientId = 1;
	required Command command = 2;
	required Vehicle vehicle = 3;
}

message SendCommandResponse {
}

message UploadRouteRequest {
	required int32 clientId = 1;
	required Route route = 2;
	required Vehicle vehicle = 3;
}

message UploadRouteResponse {
}

message GetAdsbBulbStatusRequest {
	required int32 clientId = 1;
}

message GetAdsbBulbStatusResponse {
	required bool on = 1;
}


// Licensing and Version control

message GetLicenseRequest {
	required int32 clientId = 1;
}

message GetLicenseResponse {
	optional License license = 1;
	required LicensePermissionsDto licensePermissions = 2;
}

message ActivateLicenseRequest {
	required int32 clientId = 1;
	required string activationCode = 2;
}

message ActivateLicenseResponse {
	optional License license = 1;
}

message DeactivateLicenseRequest {
	required int32 clientId = 1;
}

message DeactivateLicenseResponse {
}

message CheckForUpdatesRequest {
	required int32 clientId = 1;
}

message CheckForUpdatesResponse {
	optional VersionsInfoDto newVersions = 1;
} 

// Statistics
message SendStatisticsRequest {
	required int32 clientId = 1;
	required StatisticsDto statistics = 2;
}

message SendStatisticsResponse {
	required bool accepted = 1;
}


// Generic CRUD services

// GetObject & CreateOrUpdateObject specifics:
// If refreshDependencies field is set to false (default), object references 
// WILL NOT be initialized, even if they exist. Should be used in cases,
// that don't access dependencies data to reduce processing overhead.
// If withComposites field is set to true, domain object references,
// marked as composite references would also be affected by update operations,
// such as CreateOrUpdate and Delete

message GetObjectListRequest {
	required int32 clientId = 1;
	required string objectType = 2;
	optional bool refreshDependencies = 3 [default = false];
	repeated string refreshExcludes = 4;
	optional bool translate = 5 [default = true];
}

message GetObjectListResponse {
	required string objectType = 1;
	repeated DomainObjectWrapper objects = 2;
}

message GetObjectRequest {
	required int32 clientId = 1;
	required string objectType = 2;
	required int32 objectId = 3;
	optional bool refreshDependencies = 4 [default = false];
	repeated string refreshExcludes = 5;
	optional bool translate = 6 [default = true];
}

message GetObjectResponse {
	required string objectType = 1;
	required DomainObjectWrapper object = 2;
}

message CreateOrUpdateObjectRequest {
	required int32 clientId = 1;
	required string objectType = 2;
	required DomainObjectWrapper object = 3;
	optional bool withComposites = 4 [default = true];
	optional bool acquireLock = 5 [default = false];
}

message CreateOrUpdateObjectResponse {
	required string objectType = 1;
	required DomainObjectWrapper object = 2;
}

message UpdateObjectFieldsRequest {
	required int32 clientId = 1;
	required string objectType = 2;
	required DomainObjectWrapper object = 3;
	repeated string fieldNames = 4;
	optional bool acquireLock = 5 [default = false];
}

message UpdateObjectFieldsResponse {
	required string objectType = 1;
	required DomainObjectWrapper object = 2;
}

message DeleteObjectRequest {
	required int32 clientId = 1;
	required string objectType = 2;
	required int32 objectId = 3;
}

message DeleteObjectResponse {
	required string objectType = 1;
	required int32 objectId = 2;
	optional int32 objectVersion = 3;
}

message GetFailsafeActionsRequest {
	required int32 clientId = 1;
	repeated PlatformAndVehicleTypePairDto platformAndVehicleTypes = 2;
}

message GetFailsafeActionsResponse {
	required int32 clientId = 1;
	repeated FailsafeActionsDto failsafeActionsDto = 2;
}

message GetAlgorithmsRequest {
	required int32 clientId = 1;
	repeated PlatformAndVehicleTypePairDto platformAndVehicleTypes = 2;
}

message GetAlgorithmsResponse {
	required int32 clientId = 1;
	repeated AlgorithmsDto algorithms = 2;
}

// Locks

message AcquireLockRequest {
	required int32 clientId = 1;
	required string objectType = 2;
	required int32 objectId = 3;
}

message AcquireLockResponse {
}

message ReleaseLockRequest {
	required int32 clientId = 1;
	required string objectType = 2;
	required int32 objectId = 3;
	optional bool ifExclusive = 4 [default = false];
}

message ReleaseLockResponse {
}

message CheckLockRequest {
	required int32 clientId = 1;
	required string objectType = 2;
	required int32 objectId = 3;
}

message CheckLockResponse {
	required string objectType = 1;
	required int32 objectId = 2;
	optional Lock lock = 3; // null if object is free
}

message CheckMultipleLocksRequest {
	required int32 clientId = 1;
	required string objectType = 2;
	repeated int32 objectIds = 3;
}

message CheckMultipleLocksResponse {
	required string objectType = 1;
	repeated int32 objectIds = 2;
	repeated Lock locks = 3;
}

message GetMissionPreferencesRequest {
	required int32 clientId = 1;
	required User user = 2;
	optional Mission mission = 3;
}

message GetMissionPreferencesResponse {
	repeated MissionPreference preferences = 1;
}

message UpdateMissionPreferencesRequest {
	required int32 clientId = 1;
	repeated MissionPreference preferences = 2;
}

message UpdateMissionPreferencesResponse {
}

message DroneshareUploadRequest {
	required int32 clientId = 1;
	required Vehicle vehicle = 2;
	required int64 fromTime = 3;
	optional int64 toTime = 4;
	required string droneshareLogin = 5;
	required string dronesharePassword = 6;
	optional DronesharePrivacy dronesharePrivacy = 7;
}

message DroneshareUploadResponse {
	optional string droneshareSummaryText = 1;
	optional string droneshareViewUrl = 2;
}

message SubmitUtmOperationRequest {
	required int32 clientId = 1;
	required UtmOperation utmOperation = 2;
	required Route route = 3;
}

message SubmitUtmOperationResponse {
	required UtmOperation utmOperation = 1;
}

message GetCapabilitiesRequest {
	required int32 clientId = 1;
}

message GetCapabilitiesResponse {
	required bool utm = 1 [default = false];
}

message GetVehicleTargetLocationsRequest {
	required int32 clientId = 1;
}

message GetVehicleTargetLocationsResponse {
	required int32 clientId = 1;
	repeated VehicleTargetLocationDto targetLocations = 2;
}

// Operations

message OperationStatus {
	repeated ProgressDto progressStack = 1;
}

message OperationStream {
	required string streamId = 1;
	// empty chunk denotes end of stream
	required bytes chunk = 2;
}

message OperationStreamRequest {
	required string streamId = 1;
	required int32 chunkLength = 2;
}

message CancelOperationRequest {
	required int32 requestId = 1;
}

message CancelOperationResponse {
}

message StreamTestRequest {
	required int32 clientId = 1;
}

message StreamTestResponse {
}

message ProgressTestRequest {
	required int32 clientId = 1;
}

message ProgressTestResponse {
}

// Events

message Notification {
	required int32 subscriptionId = 1;
	required EventWrapper event = 2;
}

message SubscribeEventRequest {
	required int32 clientId = 1;
	required EventSubscriptionWrapper subscription = 2;
}

message SubscribeEventResponse {
	required int32 subscriptionId = 1;
}

message UnsubscribeEventRequest {
	required int32 clientId = 1;
	required int32 subscriptionId = 2;
}

message UnsubscribeEventResponse {
}
Clone this wiki locally