├── Sources ├── Mavsdk │ ├── templates │ │ ├── initialisms │ │ ├── type_conversions │ │ ├── enum.j2 │ │ ├── call.j2 │ │ ├── file.j2 │ │ ├── request.j2 │ │ ├── stream.j2 │ │ └── struct.j2 │ ├── tools │ │ ├── generate_docs.sh │ │ └── generate_from_protos.bash │ ├── Drone.swift │ └── Generated │ │ ├── Core.swift │ │ ├── rtk.grpc.swift │ │ ├── tune.grpc.swift │ │ ├── failure.grpc.swift │ │ ├── server_utility.grpc.swift │ │ ├── Rtk.swift │ │ ├── shell.grpc.swift │ │ ├── Shell.swift │ │ ├── geofence.grpc.swift │ │ ├── transponder.grpc.swift │ │ ├── core.grpc.swift │ │ ├── component_information.grpc.swift │ │ ├── ServerUtility.swift │ │ ├── component_information_server.grpc.swift │ │ ├── core.pb.swift │ │ ├── mocap.grpc.swift │ │ └── ManualControl.swift └── MavsdkServer │ └── MavsdkServer.swift ├── Tests ├── LinuxMain.swift ├── MavsdkIntegrationTests │ ├── CoreTest.swift │ ├── TelemetryTest.swift │ ├── MissionTest.swift │ ├── ActionTest.swift │ └── CalibrationTest.swift └── MavsdkTests │ ├── ActionTest.swift │ ├── CoreTest.swift │ ├── TelemetryTest.swift │ └── MissionTest.swift ├── .gitmodules ├── .swiftpm └── xcode │ └── package.xcworkspace │ └── contents.xcworkspacedata ├── .gitignore ├── LICENSE.md ├── Package.swift ├── .github └── workflows │ └── main.yml ├── Package.resolved └── README.md /Sources/Mavsdk/templates/initialisms: -------------------------------------------------------------------------------- 1 | ["HTTP", "HTTPS", "ID", "URL"] 2 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | var tests = [XCTestCaseEntry]() 4 | XCTMain(tests) 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Sources/Mavsdk/proto"] 2 | path = Sources/Mavsdk/proto 3 | url = https://github.com/mavlink/MAVSDK-Proto.git 4 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | *.framework 3 | *.xcframework 4 | 5 | xcuserdata/ 6 | build/ 7 | bin/ 8 | swiftpm/ 9 | 10 | .build 11 | 12 | .idea 13 | 14 | SampleCode/SwiftSampleCode/Pods/ 15 | 16 | Carthage/ 17 | docs/ 18 | venv/ 19 | ven/ 20 | -------------------------------------------------------------------------------- /Sources/Mavsdk/templates/type_conversions: -------------------------------------------------------------------------------- 1 | { 2 | "double": "Double", 3 | "float": "Float", 4 | "int64_t": "Int64", 5 | "uint64_t": "UInt64", 6 | "int32_t": "Int32", 7 | "bool": "Bool", 8 | "std::string": "String", 9 | "std::byte": "Data", 10 | "uint32_t": "UInt32", 11 | "repeated": { "prefix": "[", "suffix": "]" } 12 | } 13 | -------------------------------------------------------------------------------- /Sources/Mavsdk/tools/generate_docs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | if ! [ -x "$(command -v jazzy)" ]; then 6 | echo 'Error: jazzy is not installed.' >&2 7 | echo ' Install using: `gem install jazzy`.' >&2 8 | exit 1 9 | fi 10 | 11 | jazzy \ 12 | --clean \ 13 | --author MAVSDK developers \ 14 | --author_url https://mavsdk.mavlink.io \ 15 | --github_url https://github.com/mavlink/MAVSDK-Swift \ 16 | --github-file-prefix https://github.com/mavlink/MAVSDK-Swift/tree/master \ 17 | --module-version master \ 18 | --root-url https://mavsdk.mavlink.io/docs/swift \ 19 | --output docs/swift_output \ 20 | --module Mavsdk 21 | -------------------------------------------------------------------------------- /Tests/MavsdkIntegrationTests/CoreTest.swift: -------------------------------------------------------------------------------- 1 | import RxBlocking 2 | import XCTest 3 | @testable import Mavsdk 4 | 5 | class CoreTest: XCTestCase { 6 | 7 | func testConnectionStateEmitsWhenConnecting() throws { 8 | let expectedCount = 1 9 | 10 | let drone = Drone() 11 | _ = try drone.startMavlink 12 | .andThen(drone.core.connectionState.take(expectedCount)) 13 | .toBlocking(timeout: 2) 14 | .toArray() 15 | } 16 | 17 | func testPluginsAreRunning() throws { 18 | let expectedPlugins = ["action", "calibration", "camera", "core", "mission", "telemetry", "info"] 19 | 20 | let drone = Drone() 21 | let pluginNames = try drone.startMavlink 22 | .andThen(drone.core.listRunningPlugins()) 23 | .toBlocking() 24 | .first()!.map({ pluginInfo in pluginInfo.name }) 25 | 26 | _ = pluginNames.map({ name in XCTAssertTrue(expectedPlugins.contains(name)) }) 27 | _ = expectedPlugins.map({ name in XCTAssertTrue(pluginNames.contains(name)) }) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Tests/MavsdkIntegrationTests/TelemetryTest.swift: -------------------------------------------------------------------------------- 1 | import RxBlocking 2 | import RxTest 3 | import RxSwift 4 | import XCTest 5 | @testable import Mavsdk 6 | 7 | class TelemetryTest: XCTestCase { 8 | 9 | func testPositionEmitsValues() throws { 10 | let expectedCount = 5 11 | 12 | let drone = Drone() 13 | _ = try drone.startMavlink 14 | .andThen(drone.telemetry.position) 15 | .take(expectedCount) 16 | .toBlocking(timeout: 2) 17 | .toArray() 18 | } 19 | 20 | func testPositionCanBeSubscribedMultipleTimes() throws { 21 | let expectedCount = 5 22 | let drone = Drone() 23 | 24 | let position1 = drone.startMavlink 25 | .andThen(drone.telemetry.position) 26 | 27 | let position2 = drone.startMavlink 28 | .andThen(drone.telemetry.position) 29 | 30 | _ = try Observable.zip(position1, position2) { return ($0, $1) } 31 | .take(expectedCount) 32 | .toBlocking(timeout: 2) 33 | .toArray() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Tests/MavsdkIntegrationTests/MissionTest.swift: -------------------------------------------------------------------------------- 1 | import RxSwift 2 | import XCTest 3 | @testable import Mavsdk 4 | 5 | class MissionTest: XCTestCase { 6 | 7 | func testUploadEmptyMissionSucceeds() { 8 | let drone = Drone() 9 | _ = drone.startMavlink 10 | .andThen(drone.mission.uploadMission(missionItems: [])) 11 | .do(onError: { error in XCTFail("\(error)") }) 12 | .toBlocking() 13 | .materialize() 14 | } 15 | 16 | func testUploadOneItemSucceeds() { 17 | let drone = Drone() 18 | 19 | let missionItem = Mission.MissionItem(latitudeDeg: 47.3977121, longitudeDeg: 8.5456788, relativeAltitudeM: 42, speedMS: 8.4, isFlyThrough: false, gimbalPitchDeg: 90, gimbalYawDeg: 23, cameraAction: Mission.MissionItem.CameraAction.none, loiterTimeS: 3, cameraPhotoIntervalS: 1) 20 | 21 | _ = drone.startMavlink 22 | .andThen(drone.mission.uploadMission(missionItems: [missionItem])) 23 | .do(onError: { error in XCTFail("\(error)") }) 24 | .toBlocking() 25 | .materialize() 26 | } 27 | 28 | func testStartMissionSucceeds() { 29 | let drone = Drone() 30 | 31 | _ = drone.startMavlink 32 | .andThen(drone.mission.startMission()) 33 | .do(onError: { error in XCTFail("\(error)") }) 34 | .toBlocking() 35 | .materialize() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, Dronecode Development Team 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Sources/MavsdkServer/MavsdkServer.swift: -------------------------------------------------------------------------------- 1 | #if !os(Linux) 2 | import Foundation 3 | @_implementationOnly import mavsdk_server 4 | 5 | public class MavsdkServer { 6 | private var mavsdkServerHandle: OpaquePointer? 7 | 8 | public init() { 9 | mavsdk_server_init(&self.mavsdkServerHandle) 10 | } 11 | 12 | deinit { 13 | mavsdk_server_destroy(self.mavsdkServerHandle) 14 | } 15 | 16 | /** 17 | Run `mavsdk_server`, connecting to the drone. 18 | 19 | - Parameter systemAddress: The address on which `mavsdk_server` will listen for a MAVLink system. Note that this is about the MAVLink connection between `mavsdk_server` and the drone. 20 | - Parameter mavsdkServerPort: The port on which `mavsdk_server` will listen for a `Drone` object to connect. Note that this is about the connection between `Mavsdk` and `mavsdk_server`, and has nothing to do with MAVLink itself. 21 | - Returns: True if `mavsdk_server` detected a drone and is running, false if it failed or was stopped while connecting 22 | */ 23 | public func run(systemAddress: String = "udp://:14540", mavsdkServerPort: Int = 0) -> Bool { 24 | return (mavsdk_server_run(self.mavsdkServerHandle, systemAddress, Int32(mavsdkServerPort)) != 0) 25 | } 26 | 27 | /** 28 | - Returns: The port on which `mavsdk_server` listens for connections 29 | */ 30 | public func getPort() -> Int { 31 | return Int(mavsdk_server_get_port(self.mavsdkServerHandle!)) 32 | } 33 | 34 | /** 35 | Attach to the running `mavsdk_server`, effectively blocking until it stops 36 | */ 37 | public func attach() { 38 | mavsdk_server_attach(self.mavsdkServerHandle!) 39 | } 40 | 41 | /** 42 | Stop `mavsdk_server`. 43 | */ 44 | public func stop() { 45 | mavsdk_server_stop(mavsdkServerHandle) 46 | } 47 | } 48 | #endif 49 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.4 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "Mavsdk", 6 | platforms: [ 7 | .iOS(.v13), 8 | .macOS(.v10_15) 9 | ], 10 | products: [ 11 | .library(name: "Mavsdk", 12 | targets: [ 13 | "Mavsdk", 14 | ] 15 | ), 16 | .library(name: "MavsdkServer", 17 | targets: [ 18 | "MavsdkServer" 19 | ] 20 | ), 21 | .library(name: "mavsdk_server", 22 | targets: [ 23 | "mavsdk_server" 24 | ] 25 | ) 26 | ], 27 | dependencies: [ 28 | .package(url: "https://github.com/grpc/grpc-swift", from: "1.0.0"), 29 | .package(url: "https://github.com/ReactiveX/RxSwift.git", from: "6.5.0") 30 | ], 31 | targets: [ 32 | .target(name: "Mavsdk", 33 | dependencies: [ 34 | .product(name: "GRPC", package: "grpc-swift"), 35 | .product(name: "RxSwift", package: "RxSwift"), 36 | .product(name: "RxBlocking", package: "RxSwift") 37 | ], 38 | exclude: [ 39 | "proto", 40 | "templates", 41 | "tools" 42 | ] 43 | ), 44 | .target(name: "MavsdkServer", 45 | dependencies: [ 46 | "mavsdk_server" 47 | ] 48 | ), 49 | .binaryTarget(name: "mavsdk_server", 50 | url: "https://github.com/mavlink/MAVSDK/releases/download/v1.4.17/mavsdk_server.xcframework.zip", 51 | checksum: "e5b1f13add15892aba1315412d9aa9a9eb4eb565512e87325819d7f23dde8aec"), 52 | .testTarget(name: "MavsdkTests", 53 | dependencies: [ 54 | "Mavsdk", 55 | .product(name: "RxTest", package: "RxSwift"), 56 | .product(name: "RxBlocking", package: "RxSwift") 57 | ] 58 | ) 59 | ] 60 | ) 61 | -------------------------------------------------------------------------------- /Sources/Mavsdk/templates/enum.j2: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | {{ enum_description }} 4 | */ 5 | public enum {{ name.upper_camel_case }}: Equatable { 6 | {%- for value in values %} 7 | /// {{ value.description.rstrip() }}. 8 | case {{ value.name.lower_camel_case }} 9 | {%- endfor %} 10 | case UNRECOGNIZED(Int) 11 | 12 | internal var rpc{{ name.upper_camel_case }}: {{ package.upper_camel_case.replace('_', '').replace('.', '_') }}{% if parent_struct is not none %}_{{ parent_struct.upper_camel_case }}.{% else %}_{% endif %}{{ name.upper_camel_case }} { 13 | switch self { 14 | {%- for value in values %} 15 | case .{{ value.name.lower_camel_case }}: 16 | return .{% if value.name.uppercase.startswith(name.uppercase) %}{% set value_without_prefix = value.name.lower_camel_case[name.lower_camel_case|length:] %}{{ value_without_prefix[0].lower() + value_without_prefix[1:] }}{% else %}{{ value.name.lower_camel_case }}{% endif %} 17 | {%- endfor %} 18 | case .UNRECOGNIZED(let i): 19 | return .UNRECOGNIZED(i) 20 | } 21 | } 22 | 23 | internal static func translateFromRpc(_ rpc{{ name.upper_camel_case }}: {{ package.upper_camel_case.replace('_', '').replace('.', '_') }}{% if parent_struct is not none %}_{{ parent_struct.upper_camel_case }}.{% else %}_{% endif %}{{ name.upper_camel_case }}) -> {{ name.upper_camel_case }} { 24 | switch rpc{{ name.upper_camel_case }} { 25 | {%- for value in values %} 26 | case .{% if value.name.uppercase.startswith(name.uppercase) %}{% set value_without_prefix = value.name.lower_camel_case[name.lower_camel_case|length:] %}{{ value_without_prefix[0].lower() + value_without_prefix[1:] }}{% else %}{{ value.name.lower_camel_case }}{% endif %}: 27 | return .{{ value.name.lower_camel_case }} 28 | {%- endfor %} 29 | case .UNRECOGNIZED(let i): 30 | return .UNRECOGNIZED(i) 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Tests/MavsdkIntegrationTests/ActionTest.swift: -------------------------------------------------------------------------------- 1 | import RxSwift 2 | import XCTest 3 | @testable import Mavsdk 4 | 5 | class ActionTest: XCTestCase { 6 | 7 | func testArmSucceeds() { 8 | let drone = Drone() 9 | _ = drone.startMavlink 10 | .andThen(drone.action.arm()) 11 | .do(onError: { error in XCTFail("\(error)") }) 12 | .toBlocking() 13 | .materialize() 14 | } 15 | 16 | func testDisarmSucceeds() { 17 | let drone = Drone() 18 | _ = drone.startMavlink 19 | .andThen(drone.action.arm()) 20 | .delay(2, scheduler: MainScheduler.instance) 21 | .andThen(drone.action.disarm()) 22 | .do(onError: { (error) in XCTFail("\(error)") }) 23 | .toBlocking() 24 | .materialize() 25 | } 26 | 27 | func testTakeoffAndLandSucceeds() { 28 | let drone = Drone() 29 | _ = drone.startMavlink 30 | .andThen(drone.action.arm()) 31 | .andThen(drone.action.takeoff()) 32 | .delay(5, scheduler: MainScheduler.instance) 33 | .andThen(drone.action.land()) 34 | .do(onError: { (error) in XCTFail("\(error)") }) 35 | .toBlocking() 36 | .materialize() 37 | } 38 | 39 | func testSetAndGetReturnToLaunchAltitude() throws { 40 | let expectedFirstAltitude: Float = 32 41 | let expectedSecondAltitude: Float = 5 42 | 43 | let drone = Drone() 44 | _ = drone.startMavlink.toBlocking().materialize() 45 | 46 | let firstAltitude = try drone.action.setReturnToLaunchAltitude(relativeAltitudeM: expectedFirstAltitude) 47 | .andThen(drone.action.getReturnToLaunchAltitude()) 48 | .toBlocking().single() 49 | 50 | XCTAssertEqual(expectedFirstAltitude, firstAltitude) 51 | 52 | let secondAltitude = try drone.action.setReturnToLaunchAltitude(relativeAltitudeM: expectedSecondAltitude) 53 | .andThen(drone.action.getReturnToLaunchAltitude()) 54 | .toBlocking().single() 55 | 56 | XCTAssertEqual(expectedSecondAltitude, secondAltitude) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Tests/MavsdkIntegrationTests/CalibrationTest.swift: -------------------------------------------------------------------------------- 1 | import RxSwift 2 | import XCTest 3 | @testable import Mavsdk 4 | 5 | class CalibrationTest: XCTestCase { 6 | 7 | /* 8 | func testGyroCalibration() { 9 | let expectation = XCTestExpectation(description: "Gyro calibration succeeded.") 10 | 11 | let core = Core() 12 | core.connect().toBlocking().materialize() 13 | let calibration = Calibration(address: "localhost", port: 50051) 14 | 15 | calibration.calibrateGyro 16 | .do(onNext: { progressData in print(progressData) }, 17 | onError: { error in print(error) }) 18 | .subscribe(onError: { error in XCTFail(); expectation.fulfill() }, 19 | onCompleted: { expectation.fulfill() }) 20 | 21 | wait(for: [expectation], timeout: 180.0) 22 | } 23 | 24 | func testAccelerometerCalibration() { 25 | let expectation = XCTestExpectation(description: "Accelerometer calibration succeeded.") 26 | 27 | let core = Core() 28 | core.connect().toBlocking().materialize() 29 | let calibration = Calibration(address: "localhost", port: 50051) 30 | 31 | calibration.calibrateAccelerometer 32 | .do(onNext: { progressData in print(progressData) }, 33 | onError: { error in print(error) }) 34 | .subscribe(onError: { error in XCTFail(); expectation.fulfill() }, 35 | onCompleted: { expectation.fulfill() }) 36 | 37 | wait(for: [expectation], timeout: 180.0) 38 | } 39 | 40 | func testMagnetometerCalibration() { 41 | let expectation = XCTestExpectation(description: "Magnetometer calibration succeeded.") 42 | 43 | let core = Core() 44 | core.connect().toBlocking().materialize() 45 | let calibration = Calibration(address: "localhost", port: 50051) 46 | 47 | calibration.calibrateMagnetometer 48 | .do(onNext: { progressData in print(progressData) }, 49 | onError: { error in print(error) }) 50 | .subscribe(onError: { error in XCTFail(); expectation.fulfill() }, 51 | onCompleted: { expectation.fulfill() }) 52 | 53 | wait(for: [expectation], timeout: 180.0) 54 | } 55 | */ 56 | } 57 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | tags: 8 | - "*" 9 | pull_request: 10 | branches: 11 | - "*" 12 | 13 | jobs: 14 | build: 15 | name: build 16 | runs-on: macos-latest 17 | steps: 18 | - uses: actions/checkout@v2 19 | with: 20 | submodules: recursive 21 | - name: build 22 | run: swift build 23 | generate-from-proto: 24 | name: generate from protos 25 | runs-on: macos-latest 26 | steps: 27 | - uses: actions/checkout@v2 28 | with: 29 | submodules: recursive 30 | - name: install tools 31 | run: pip3 install protoc-gen-mavsdk && brew install protobuf || brew link --overwrite protobuf 32 | - name: generate from protos 33 | run: bash Sources/Mavsdk/tools/generate_from_protos.bash 34 | - name: check for diff 35 | run: git diff --exit-code 36 | generate-docs: 37 | name: generate documentation 38 | runs-on: macos-latest 39 | steps: 40 | - uses: actions/checkout@v2 41 | with: 42 | submodules: recursive 43 | - name: install tools 44 | run: gem install jazzy && pip3 install --user s3cmd python-magic 45 | - name: generate docs 46 | run: bash Sources/Mavsdk/tools/generate_docs.sh 47 | - name: deploy docs (if main) 48 | env: 49 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} 50 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 51 | if: github.ref == 'refs/heads/main' 52 | run: | 53 | export PATH=$PATH:$(python3 -m site --user-base)/bin 54 | s3cmd --acl-public --add-header="Cache-Control:public, max-age=0" put --recursive docs/swift_output/* s3://mavsdk-swift-docs/main/; 55 | - name: deploy docs (if tag) 56 | env: 57 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} 58 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 59 | if: startsWith(github.ref, 'refs/tags/') 60 | run: 61 | export PATH=$PATH:$(python3 -m site --user-base)/bin 62 | s3cmd --acl-public --add-header="Cache-Control:public, max-age=0" put --recursive docs/swift_output/* s3://mavsdk-swift-docs/${GITHUB_REF#refs/tags/}/; 63 | -------------------------------------------------------------------------------- /Sources/Mavsdk/templates/call.j2: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | {{ method_description }} 4 | 5 | {% if params|length == 1 -%} 6 | - Parameter {{ params[0].name.lower_camel_case }}:{{ params[0].description.rstrip() }} 7 | {% elif params|length > 1 -%} 8 | - Parameters: 9 | {%- for param in params %} 10 | - {{ param.name.lower_camel_case }}:{{ param.description.rstrip() }} 11 | {%- endfor %} 12 | {% endif %} 13 | */ 14 | public func {{ name.lower_camel_case }}({% for param in params %}{{ param.name.lower_camel_case }}: {{ param.type_info.name }}{{ ", " if not loop.last }}{% endfor %}) -> Completable { 15 | return Completable.create { completable in 16 | {% if params|length > 0 %}var{% else %}let{% endif %} request = {{ package.upper_camel_case.replace('_', '').replace('.', '_') }}_{{ name.upper_camel_case }}Request() 17 | 18 | {% for param in params %} 19 | {% if param.type_info.is_primitive %} 20 | request.{{ param.name.lower_camel_case }} = {{ param.name.lower_camel_case }} 21 | {% elif param.type_info.is_repeated %} 22 | {{ param.name.lower_camel_case }}.forEach({ elem in request.{{ param.name.lower_camel_case }}.append(elem.rpc{{ param.type_info.inner_name }}) }) 23 | {% else %} 24 | request.{{ param.name.lower_camel_case }} = {{ param.name.lower_camel_case }}.rpc{{ param.type_info.name }} 25 | {% endif %} 26 | {% endfor %} 27 | 28 | do { 29 | {% if has_result %} 30 | let response = self.service.{{ name.lower_camel_case }}(request) 31 | 32 | let result = try response.response.wait().{{ plugin_name.lower_camel_case }}Result 33 | if (result.result == {{ package.upper_camel_case.replace('_', '').replace('.', '_') }}_{{ plugin_name.upper_camel_case }}Result.Result.success) { 34 | completable(.completed) 35 | } else { 36 | completable(.error({{ plugin_name.upper_camel_case }}Error(code: {{ plugin_name.upper_camel_case }}Result.Result.translateFromRpc(result.result), description: result.resultStr))) 37 | } 38 | {% else %} 39 | let _ = try self.service.{{ name.lower_camel_case }}(request) 40 | completable(.completed) 41 | {% endif %} 42 | } catch { 43 | completable(.error(error)) 44 | } 45 | 46 | return Disposables.create() 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Sources/Mavsdk/templates/file.j2: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import RxSwift 3 | import GRPC 4 | import NIO 5 | 6 | /** 7 | {{ class_description }} 8 | */ 9 | public class {{ plugin_name.upper_camel_case }} { 10 | private let service: {{ package.upper_camel_case.replace('_', '').replace('.', '_') }}_{{ plugin_name.upper_camel_case }}ServiceClient 11 | private let scheduler: SchedulerType 12 | private let clientEventLoopGroup: EventLoopGroup 13 | 14 | /** 15 | Initializes a new `{{ plugin_name.upper_camel_case }}` plugin. 16 | 17 | Normally never created manually, but used from the `Drone` helper class instead. 18 | 19 | - Parameters: 20 | - address: The address of the `MavsdkServer` instance to connect to 21 | - port: The port of the `MavsdkServer` instance to connect to 22 | - scheduler: The scheduler to be used by `Observable`s 23 | */ 24 | public convenience init(address: String = "localhost", 25 | port: Int32 = 50051, 26 | scheduler: SchedulerType = ConcurrentDispatchQueueScheduler(qos: .background)) { 27 | let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 2) 28 | let channel = ClientConnection.insecure(group: eventLoopGroup).connect(host: address, port: Int(port)) 29 | let service = {{ package.upper_camel_case.replace('_', '').replace('.', '_') }}_{{ plugin_name.upper_camel_case }}ServiceClient(channel: channel) 30 | 31 | self.init(service: service, scheduler: scheduler, eventLoopGroup: eventLoopGroup) 32 | } 33 | 34 | init(service: {{ package.upper_camel_case.replace('_', '').replace('.', '_') }}_{{ plugin_name.upper_camel_case }}ServiceClient, scheduler: SchedulerType, eventLoopGroup: EventLoopGroup) { 35 | self.service = service 36 | self.scheduler = scheduler 37 | self.clientEventLoopGroup = eventLoopGroup 38 | } 39 | 40 | public struct Runtime{{ plugin_name.upper_camel_case }}Error: Error { 41 | public let description: String 42 | 43 | init(_ description: String) { 44 | self.description = description 45 | } 46 | } 47 | 48 | {% if has_result %} 49 | public struct {{ plugin_name.upper_camel_case }}Error: Error { 50 | public let code: {{ plugin_name.upper_camel_case }}.{{ plugin_name.upper_camel_case }}Result.Result 51 | public let description: String 52 | } 53 | {% endif %} 54 | 55 | {%- for enum in enums %} 56 | {{ indent(enum, 1) }} 57 | {%- endfor %} 58 | 59 | {% for struct in structs %} 60 | {{ indent(struct, 1) }} 61 | {% endfor %} 62 | 63 | {%- for method in methods %} 64 | {{ indent(method, 1) }} 65 | {%- endfor %} 66 | } 67 | -------------------------------------------------------------------------------- /Sources/Mavsdk/templates/request.j2: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | {{ method_description }} 4 | 5 | {% if params|length == 1 -%} 6 | - Parameter {{ params[0].name.lower_camel_case }}:{{ params[0].description.rstrip() }} 7 | {% elif params|length > 1 -%} 8 | - Parameters: 9 | {%- for param in params %} 10 | - {{ param.name.lower_camel_case }}:{{ param.description.rstrip() }} 11 | {%- endfor %} 12 | {% endif %} 13 | */ 14 | public func {{ name.lower_camel_case }}({% for param in params %}{{ param.name.lower_camel_case }}: {{ param.type_info.name }}{{ ", " if not loop.last }}{% endfor %}) -> Single<{{ return_type.name }}> { 15 | return Single<{{ return_type.name }}>.create { single in 16 | {% if params|length > 0 %}var{% else %}let{% endif %} request = {{ package.upper_camel_case.replace('_', '').replace('.', '_') }}_{{ name.upper_camel_case }}Request() 17 | 18 | {% for param in params %} 19 | {% if param.type_info.is_primitive %} 20 | request.{{ param.name.lower_camel_case }} = {{ param.name.lower_camel_case }} 21 | {% else %} 22 | request.{{ param.name.lower_camel_case }} = {{ param.name.lower_camel_case }}.rpc{{ param.name.upper_camel_case }} 23 | {% endif %} 24 | {% endfor %} 25 | 26 | do { 27 | let response = self.service.{{ name.lower_camel_case }}(request) 28 | 29 | {% if has_result %} 30 | let result = try response.response.wait().{{ plugin_name.lower_camel_case }}Result 31 | if (result.result != {{ package.upper_camel_case.replace('_', '').replace('.', '_') }}_{{ plugin_name.upper_camel_case }}Result.Result.success) { 32 | single(.failure({{ plugin_name.upper_camel_case }}Error(code: {{ plugin_name.upper_camel_case }}Result.Result.translateFromRpc(result.result), description: result.resultStr))) 33 | 34 | return Disposables.create() 35 | } 36 | {% endif %} 37 | 38 | {% if return_type.is_primitive -%} 39 | let {{ return_name.lower_camel_case }} = try response.response.wait().{{ return_name.lower_camel_case }} 40 | {% else %} 41 | {% if return_type.is_repeated -%} 42 | let {{ return_name.lower_camel_case }} = try response.response.wait().{{ return_name.lower_camel_case }}.map{ {{ return_type.inner_name }}.translateFromRpc($0) } 43 | {%- else -%} 44 | let {{ return_name.lower_camel_case }} = try {{ return_type.inner_name }}.translateFromRpc(response.response.wait().{{ return_name.lower_camel_case }}) 45 | {%- endif %} 46 | {% endif %} 47 | single(.success({{ return_name.lower_camel_case }})) 48 | } catch { 49 | single(.failure(error)) 50 | } 51 | 52 | return Disposables.create() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "grpc-swift", 6 | "repositoryURL": "https://github.com/grpc/grpc-swift", 7 | "state": { 8 | "branch": null, 9 | "revision": "d772b688d718c2eb29f99b535fc4d92ebba031c5", 10 | "version": "1.8.1" 11 | } 12 | }, 13 | { 14 | "package": "RxSwift", 15 | "repositoryURL": "https://github.com/ReactiveX/RxSwift.git", 16 | "state": { 17 | "branch": null, 18 | "revision": "b4307ba0b6425c0ba4178e138799946c3da594f8", 19 | "version": "6.5.0" 20 | } 21 | }, 22 | { 23 | "package": "swift-log", 24 | "repositoryURL": "https://github.com/apple/swift-log.git", 25 | "state": { 26 | "branch": null, 27 | "revision": "5d66f7ba25daf4f94100e7022febf3c75e37a6c7", 28 | "version": "1.4.2" 29 | } 30 | }, 31 | { 32 | "package": "swift-nio", 33 | "repositoryURL": "https://github.com/apple/swift-nio.git", 34 | "state": { 35 | "branch": null, 36 | "revision": "124119f0bb12384cef35aa041d7c3a686108722d", 37 | "version": "2.40.0" 38 | } 39 | }, 40 | { 41 | "package": "swift-nio-extras", 42 | "repositoryURL": "https://github.com/apple/swift-nio-extras.git", 43 | "state": { 44 | "branch": null, 45 | "revision": "a75e92bde3683241c15df3dd905b7a6dcac4d551", 46 | "version": "1.12.1" 47 | } 48 | }, 49 | { 50 | "package": "swift-nio-http2", 51 | "repositoryURL": "https://github.com/apple/swift-nio-http2.git", 52 | "state": { 53 | "branch": null, 54 | "revision": "108ac15087ea9b79abb6f6742699cf31de0e8772", 55 | "version": "1.22.0" 56 | } 57 | }, 58 | { 59 | "package": "swift-nio-ssl", 60 | "repositoryURL": "https://github.com/apple/swift-nio-ssl.git", 61 | "state": { 62 | "branch": null, 63 | "revision": "fd5f38b0039148e76c2e863a2fc868cc39bb451b", 64 | "version": "2.20.1" 65 | } 66 | }, 67 | { 68 | "package": "swift-nio-transport-services", 69 | "repositoryURL": "https://github.com/apple/swift-nio-transport-services.git", 70 | "state": { 71 | "branch": null, 72 | "revision": "2cb54f91ddafc90832c5fa247faf5798d0a7c204", 73 | "version": "1.13.0" 74 | } 75 | }, 76 | { 77 | "package": "SwiftProtobuf", 78 | "repositoryURL": "https://github.com/apple/swift-protobuf.git", 79 | "state": { 80 | "branch": null, 81 | "revision": "e1499bc69b9040b29184f7f2996f7bab467c1639", 82 | "version": "1.19.0" 83 | } 84 | } 85 | ] 86 | }, 87 | "version": 1 88 | } 89 | -------------------------------------------------------------------------------- /Sources/Mavsdk/tools/generate_from_protos.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | command -v protoc || { echo >&2 "Protobuf needs to be installed (e.g. '$ brew install protobuf') for this script to run!"; exit 1; } 6 | 7 | command -v protoc-gen-mavsdk > /dev/null || { 8 | echo "------------------------" 9 | echo "Error" 10 | echo "------------------------" 11 | echo >&2 "'protoc-gen-mavsdk' not found in PATH" 12 | echo >&2 "" 13 | echo >&2 "You can install it using pip:" 14 | echo >&2 "" 15 | echo >&2 "pip3 install protoc-gen-mavsdk" 16 | exit 1 17 | } 18 | 19 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 20 | PB_PLUGINS_DIR=${PB_PLUGINS_DIR:-"${SCRIPT_DIR}/../proto/pb_plugins"} 21 | PROTO_DIR=${PROTO_DIR:-"${SCRIPT_DIR}/../proto/protos"} 22 | OUTPUT_DIR=${OUTPUT_DIR:-"${SCRIPT_DIR}/../Generated"} 23 | 24 | PLUGIN_LIST=$(cd ${PROTO_DIR} && ls -d */ | sed 's:/*$::') 25 | 26 | if [ ! -d ${PROTO_DIR} ]; then 27 | echo "Script is not in the right location! It will look for the proto files in '${PROTO_DIR}', which doesn't exist!" 28 | 29 | exit 1 30 | fi 31 | 32 | if [ ! -d ${OUTPUT_DIR} ]; then 33 | echo "Script is not in the right location! It is made to generate the files in '${OUTPUT_DIR}', which doesn't exist!" 34 | 35 | exit 1 36 | fi 37 | 38 | echo "" 39 | echo "-------------------------------" 40 | echo "Generating pb and grpc.pb files" 41 | echo "-------------------------------" 42 | echo "" 43 | 44 | TMP_DIR=${TMP_DIR:-"$(mktemp -d)"} 45 | echo "Temporary directory for this build: ${TMP_DIR}" 46 | 47 | if [ ! -d ${TMP_DIR}/grpc-swift ]; then 48 | echo "" 49 | echo "--- Cloning grpc-swift" 50 | echo "" 51 | 52 | git -C ${TMP_DIR} clone https://github.com/grpc/grpc-swift -b "1.0.0" 53 | fi 54 | 55 | make -C ${TMP_DIR}/grpc-swift plugins 56 | PROTOC_GEN_SWIFT=${TMP_DIR}/grpc-swift/.build/release/protoc-gen-swift 57 | PROTOC_GEN_GRPC_SWIFT=${TMP_DIR}/grpc-swift/.build/release/protoc-gen-grpc-swift 58 | 59 | for plugin in ${PLUGIN_LIST}; do 60 | if [ "$plugin" = "tracking_server" ]; then 61 | continue 62 | fi 63 | 64 | if [ "$plugin" = "param_server" ]; then 65 | continue 66 | fi 67 | protoc ${plugin}.proto -I${PROTO_DIR} -I${PROTO_DIR}/${plugin} --swift_out=${OUTPUT_DIR} --swiftgrpc_out=${OUTPUT_DIR} --plugin=protoc-gen-swift=${PROTOC_GEN_SWIFT} --plugin=protoc-gen-swiftgrpc=${PROTOC_GEN_GRPC_SWIFT} 68 | done 69 | 70 | echo "" 71 | echo "-------------------------------" 72 | echo "Generating the SDK wrappers" 73 | echo "-------------------------------" 74 | echo "" 75 | 76 | export TEMPLATE_PATH=${TEMPLATE_PATH:-"${SCRIPT_DIR}/../templates"} 77 | 78 | for plugin in ${PLUGIN_LIST}; do 79 | if [ "$plugin" = "tracking_server" ]; then 80 | continue 81 | fi 82 | 83 | if [ "$plugin" = "param_server" ]; then 84 | continue 85 | fi 86 | protoc ${plugin}.proto --plugin=protoc-gen-custom=$(which protoc-gen-mavsdk) -I${PROTO_DIR} -I${PROTO_DIR}/${plugin} --custom_out=${OUTPUT_DIR} --custom_opt=file_ext=swift 87 | done 88 | -------------------------------------------------------------------------------- /Sources/Mavsdk/templates/stream.j2: -------------------------------------------------------------------------------- 1 | 2 | {% if not is_finite %} 3 | /** 4 | {{ method_description }} 5 | */ 6 | public lazy var {{ name.lower_camel_case }}: Observable<{% if return_type %}{{ return_type.name }}{% else %}Void{% endif %}> = create{{ name.upper_camel_case }}Observable({% for param in params %}{{ param.name.lower_camel_case }}: {{ param.type_info.name }}{{ ", " if not loop.last }}{% endfor %}) 7 | {% endif %} 8 | 9 | {% if is_finite %} 10 | /** 11 | {{ method_description }} 12 | */ 13 | {% endif %} 14 | {% if is_finite %}public func {{ name.lower_camel_case }}{% else %}private func create{{ name.upper_camel_case }}Observable{% endif %}({% for param in params %}{{ param.name.lower_camel_case }}: {{ param.type_info.name }}{{ ", " if not loop.last }}{% endfor %}) -> Observable<{% if return_type %}{{ return_type.name }}{% else %}Void{% endif %}> { 15 | return Observable.create { [unowned self] observer in 16 | {% if params|length > 0 %}var{% else %}let{% endif %} request = {{ package.upper_camel_case.replace('_', '').replace('.', '_') }}_Subscribe{{ name.upper_camel_case }}Request() 17 | 18 | {% for param in params %} 19 | {% if param.type_info.is_primitive %} 20 | request.{{ param.name.lower_camel_case }} = {{ param.name.lower_camel_case }} 21 | {% else %} 22 | request.{{ param.name.lower_camel_case }} = {{ param.name.lower_camel_case }}.rpc{{ param.name.upper_camel_case }} 23 | {% endif %} 24 | {% endfor %} 25 | 26 | let serverStreamingCall = self.service.subscribe{{ name.upper_camel_case }}(request, handler: { (response) in 27 | 28 | {% if return_type.is_repeated %} 29 | let {{ name.lower_camel_case }} = response.{{ return_name.lower_camel_case }}.map{ {{ return_type.inner_name }}.translateFromRpc($0) } 30 | {% else %} 31 | {% if return_type.is_primitive %} 32 | let {{ name.lower_camel_case }} = response.{{ return_name.lower_camel_case }}{% if return_name.lower_snake_case.endswith("type") %}_p{% endif %} 33 | {% else %} 34 | let {{ name.lower_camel_case }} = {{ return_type.name }}.translateFromRpc(response.{{ return_name.lower_camel_case }}) 35 | {%- endif %} 36 | {% endif %} 37 | 38 | {% if has_result %} 39 | let result = {{ plugin_name.upper_camel_case }}Result.translateFromRpc(response.{{ plugin_name.lower_camel_case }}Result) 40 | 41 | switch (result.result) { 42 | case .success: 43 | observer.onCompleted() 44 | case .next: 45 | observer.onNext({{ name.lower_camel_case }}) 46 | default: 47 | observer.onError({{ plugin_name.upper_camel_case }}Error(code: result.result, description: result.resultStr)) 48 | } 49 | {% else %} 50 | observer.onNext({{ name.lower_camel_case }}) 51 | {% endif %} 52 | }) 53 | 54 | return Disposables.create { 55 | serverStreamingCall.cancel(promise: nil) 56 | } 57 | } 58 | .retry { error in 59 | error.map { 60 | guard $0 is Runtime{{ plugin_name.upper_camel_case }}Error else { throw $0 } 61 | } 62 | } 63 | .share(replay: 1) 64 | } 65 | -------------------------------------------------------------------------------- /Sources/Mavsdk/templates/struct.j2: -------------------------------------------------------------------------------- 1 | /** 2 | {{ struct_description }} 3 | */ 4 | public struct {{ name.upper_camel_case }}: Equatable { 5 | {%- for field in fields %} 6 | public let {{ field.name.lower_camel_case }}: {{ field.type_info.name }} 7 | {%- endfor %} 8 | 9 | {% for nested_enum in nested_enums %} 10 | {{ '\n' + indent(nested_enums[nested_enum], 1) }} 11 | {% endfor %} 12 | 13 | /** 14 | Initializes a new `{{ name.upper_camel_case }}`. 15 | 16 | {% if fields|length == 1 %} 17 | - Parameter {{ fields[0].name.lower_camel_case }}: {{ fields[0].description.rstrip() }} 18 | {% elif fields|length > 1 %} 19 | - Parameters: 20 | {% for field in fields %} 21 | - {{ field.name.lower_camel_case }}: {{ field.description.rstrip() }} 22 | {% endfor %} 23 | {% endif %} 24 | */ 25 | public init({% for field in fields %}{{ field.name.lower_camel_case }}: {{ field.type_info.name }}{{ ", " if not loop.last }}{% endfor %}) { 26 | {%- for field in fields %} 27 | self.{{ field.name.lower_camel_case }} = {{ field.name.lower_camel_case }} 28 | {%- endfor %} 29 | } 30 | 31 | internal var rpc{{ name.upper_camel_case }}: {{ package.upper_camel_case.replace('_', '').replace('.', '_') }}_{{ name.upper_camel_case }} { 32 | var rpc{{ name.upper_camel_case }} = {{ package.upper_camel_case.replace('_', '').replace('.', '_') }}_{{ name.upper_camel_case }}() 33 | 34 | {%- for field in fields %} 35 | {% if field.type_info.is_repeated %} 36 | {% if field.type_info.is_primitive %} 37 | rpc{{ name.upper_camel_case }}.{{ field.name.lower_camel_case }} = {{ field.name.lower_camel_case }} 38 | {% else %} 39 | rpc{{ name.upper_camel_case }}.{{ field.name.lower_camel_case }} = {{ field.name.lower_camel_case }}.map{ $0.rpc{{ field.type_info.inner_name }} } 40 | {% endif %} 41 | {% else %} 42 | {% if field.type_info.is_primitive %} 43 | rpc{{ name.upper_camel_case }}.{{ field.name.lower_camel_case }}{% if field.name.lower_camel_case.startswith("has") %}_p{% endif %} = {{ field.name.lower_camel_case }} 44 | {% else %} 45 | rpc{{ name.upper_camel_case }}.{{ field.name.lower_camel_case }} = {{ field.name.lower_camel_case }}.rpc{{ field.type_info.name }} 46 | {% endif %} 47 | {% endif %} 48 | {%- endfor %} 49 | 50 | return rpc{{ name.upper_camel_case }} 51 | } 52 | 53 | internal static func translateFromRpc(_ rpc{{ name.upper_camel_case }}: {{ package.upper_camel_case.replace('_', '').replace('.', '_') }}_{{ name.upper_camel_case }}) -> {{ name.upper_camel_case }} { 54 | return {{ name.upper_camel_case }}({% for field in fields %}{{ field.name.lower_camel_case }}: {% if field.type_info.is_repeated %}{%- if field.type_info.is_primitive %}rpc{{ name.upper_camel_case }}.{{ field.name.lower_camel_case }}{%- else %}rpc{{ name.upper_camel_case }}.{{ field.name.lower_camel_case }}.map{ {{ field.type_info.inner_name }}.translateFromRpc($0) }{% endif %}{%- else %}{%- if field.type_info.is_primitive %}rpc{{ name.upper_camel_case }}.{{ field.name.lower_camel_case }}{% if field.name.lower_camel_case.startswith("has") %}_p{% endif %}{% else %}{{ field.type_info.name }}.translateFromRpc(rpc{{ name.upper_camel_case }}.{{ field.name.lower_camel_case }}){% endif %}{% endif %}{{ ", " if not loop.last }}{% endfor %}) 55 | } 56 | 57 | public static func == (lhs: {{ name.upper_camel_case }}, rhs: {{ name.upper_camel_case }}) -> Bool { 58 | return lhs.{{ fields[0].name.lower_camel_case }} == rhs.{{ fields[0].name.lower_camel_case }} 59 | {%- for field in fields[1:] %} 60 | && lhs.{{ field.name.lower_camel_case }} == rhs.{{ field.name.lower_camel_case }} 61 | {%- endfor %} 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Tests/MavsdkTests/ActionTest.swift: -------------------------------------------------------------------------------- 1 | //import XCTest 2 | //import RxBlocking 3 | //import RxSwift 4 | //import RxTest 5 | //@testable import Mavsdk 6 | // 7 | //class ActionTest: XCTestCase { 8 | // 9 | // let ARBITRARY_ALTITUDE: Float = 123.5 10 | // let ARBITRARY_SPEED: Float = 321.5 11 | // 12 | // let actionResultsArray: [Mavsdk_Rpc_Action_ActionResult.Result] = [.busy, .commandDenied, .commandDeniedNotLanded, .commandDeniedLandedStateUnknown, .connectionError, .noSystem, .noVtolTransitionSupport, .timeout, .unknown, .vtolTransitionSupportUnknown] 13 | // 14 | // func testArmSucceedsOnSuccess() throws { 15 | // try armWithFakeResult(result: Mavsdk_Rpc_Action_ActionResult.Result.success) 16 | // } 17 | // 18 | // func testArmFailsOnFailure() throws { 19 | // try actionResultsArray.forEach { result in 20 | // try armWithFakeResult(result: result) 21 | // } 22 | // } 23 | // 24 | // func armWithFakeResult(result: Mavsdk_Rpc_Action_ActionResult.Result) throws { 25 | // let fakeService = Mavsdk_Rpc_Action_ActionServiceServiceTestStub() 26 | // var response = Mavsdk_Rpc_Action_ArmResponse() 27 | // response.actionResult.result = result 28 | // fakeService.armResponses.append(response) 29 | // 30 | // let scheduler = TestScheduler(initialClock: 0) 31 | // let action = Action(service: fakeService, scheduler: scheduler) 32 | // 33 | // scheduler.start() 34 | // _ = action.arm().toBlocking().materialize() 35 | // } 36 | // 37 | // func testDisarmSucceedsOnSuccess() throws { 38 | // try disarmWithFakeResult(result: Mavsdk_Rpc_Action_ActionResult.Result.success) 39 | // } 40 | // 41 | // func testDisarmFailsOnFailure() throws { 42 | // try actionResultsArray.forEach { result in 43 | // try disarmWithFakeResult(result: result) 44 | // } 45 | // } 46 | // 47 | // func disarmWithFakeResult(result: Mavsdk_Rpc_Action_ActionResult.Result) throws { 48 | // let fakeService = Mavsdk_Rpc_Action_ActionServiceServiceTestStub() 49 | // var response = Mavsdk_Rpc_Action_DisarmResponse() 50 | // response.actionResult.result = result 51 | // fakeService.disarmResponses.append(response) 52 | // 53 | // let scheduler = TestScheduler(initialClock: 0) 54 | // let client = Action(service: fakeService, scheduler: scheduler) 55 | // 56 | // scheduler.start() 57 | // _ = client.disarm().toBlocking().materialize() 58 | // } 59 | // 60 | // func testReturnToLaunchSucceedsOnSuccess() throws { 61 | // try returnToLaunchWithFakeResult(result: Mavsdk_Rpc_Action_ActionResult.Result.success) 62 | // } 63 | // 64 | // func testReturnToLaunchFailsOnFailure() throws { 65 | // try actionResultsArray.forEach { result in 66 | // try returnToLaunchWithFakeResult(result: result) 67 | // } 68 | // } 69 | // 70 | // func returnToLaunchWithFakeResult(result: Mavsdk_Rpc_Action_ActionResult.Result) throws { 71 | // let fakeService = Mavsdk_Rpc_Action_ActionServiceServiceTestStub() 72 | // var response = Mavsdk_Rpc_Action_ReturnToLaunchResponse() 73 | // response.actionResult.result = result 74 | // fakeService.returnToLaunchResponses.append(response) 75 | // 76 | // let scheduler = TestScheduler(initialClock: 0) 77 | // let client = Action(service: fakeService, scheduler: scheduler) 78 | // 79 | // scheduler.start() 80 | // _ = client.returnToLaunch().toBlocking().materialize() 81 | // } 82 | // 83 | // func testTransitionToFixedWingsSucceedsOnSuccess() throws { 84 | // try transitionToFixedWingsWithFakeResult(result: Mavsdk_Rpc_Action_ActionResult.Result.success) 85 | // } 86 | // 87 | // func testTransitionToFixedWingsFailsOnFailure() throws { 88 | // try actionResultsArray.forEach { result in 89 | // try transitionToFixedWingsWithFakeResult(result: result) 90 | // } 91 | // } 92 | // 93 | // func transitionToFixedWingsWithFakeResult(result: Mavsdk_Rpc_Action_ActionResult.Result) throws { 94 | // let fakeService = Mavsdk_Rpc_Action_ActionServiceServiceTestStub() 95 | // var response = Mavsdk_Rpc_Action_TransitionToFixedWingResponse() 96 | // response.actionResult.result = result 97 | // fakeService.transitionToFixedWingResponses.append(response) 98 | // 99 | // let scheduler = TestScheduler(initialClock: 0) 100 | // let client = Action(service: fakeService, scheduler: scheduler) 101 | // 102 | // scheduler.start() 103 | // _ = client.transitionToFixedWing().toBlocking().materialize() 104 | // } 105 | //} 106 | -------------------------------------------------------------------------------- /Sources/Mavsdk/Drone.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import RxSwift 3 | import MavsdkServer 4 | 5 | public class Drone { 6 | private let scheduler: SchedulerType 7 | public var mavsdkServer: MavsdkServer? 8 | 9 | public var action: Action! 10 | public var calibration: Calibration! 11 | public var camera: Camera! 12 | public var core: Core! 13 | public var failure: Failure! 14 | public var followMe: FollowMe! 15 | public var ftp: Ftp! 16 | public var geofence: Geofence! 17 | public var gimbal: Gimbal! 18 | public var info: Info! 19 | public var logFiles: LogFiles! 20 | public var manualControl: ManualControl! 21 | public var mission: Mission! 22 | public var missionRaw: MissionRaw! 23 | public var mocap: Mocap! 24 | public var offboard: Offboard! 25 | public var param: Param! 26 | public var rtk: Rtk! 27 | public var shell: Shell! 28 | public var telemetry: Telemetry! 29 | public var transponder: Transponder! 30 | public var tune: Tune! 31 | 32 | public init(scheduler: SchedulerType = ConcurrentDispatchQueueScheduler(qos: .background)) { 33 | self.scheduler = MainScheduler.instance 34 | } 35 | 36 | enum ConnectionError: Swift.Error { 37 | case connectionFailed 38 | case connectionStopped 39 | } 40 | 41 | /** 42 | * Create an instance of MavsdkServer and running with `systemAddress`, which is the address of the drone. 43 | */ 44 | public func connect(systemAddress: String = "udp://:14540") -> Completable { 45 | return Completable.create { completable in 46 | self.mavsdkServer = MavsdkServer() 47 | let isRunning = self.mavsdkServer!.run(systemAddress: systemAddress) 48 | 49 | if (!isRunning) { 50 | completable(.error(ConnectionError.connectionFailed)) 51 | return Disposables.create() 52 | } 53 | 54 | if let mavsdkServer = self.mavsdkServer { 55 | self.initPlugins(address: "localhost", port: Int32(mavsdkServer.getPort())) 56 | } else { 57 | completable(.error(ConnectionError.connectionStopped)) 58 | return Disposables.create() 59 | } 60 | 61 | completable(.completed) 62 | return Disposables.create() 63 | } 64 | } 65 | 66 | /** 67 | * Connect MAVSDK to an already-running instance of MavsdkServer, locally or somewhere on the network. 68 | */ 69 | public func connect(mavsdkServerAddress: String, mavsdkServerPort: Int32 = 50051) -> Completable { 70 | return Completable.create { completable in 71 | self.initPlugins(address: mavsdkServerAddress, port: mavsdkServerPort) 72 | completable(.completed) 73 | return Disposables.create() 74 | } 75 | } 76 | 77 | private func initPlugins(address: String = "localhost", port: Int32 = 50051) { 78 | self.action = Action(address: address, port: port, scheduler: scheduler) 79 | self.calibration = Calibration(address: address, port: port, scheduler: scheduler) 80 | self.camera = Camera(address: address, port: port, scheduler: scheduler) 81 | self.core = Core(address: address, port: port, scheduler: scheduler) 82 | self.failure = Failure(address: address, port: port, scheduler: scheduler) 83 | self.followMe = FollowMe(address: address, port: port, scheduler: scheduler) 84 | self.ftp = Ftp(address: address, port: port, scheduler: scheduler) 85 | self.geofence = Geofence(address: address, port: port, scheduler: scheduler) 86 | self.gimbal = Gimbal(address: address, port: port, scheduler: scheduler) 87 | self.info = Info(address: address, port: port, scheduler: scheduler) 88 | self.logFiles = LogFiles(address: address, port: port, scheduler: scheduler) 89 | self.manualControl = ManualControl(address: address, port: port, scheduler: scheduler) 90 | self.mission = Mission(address: address, port: port, scheduler: scheduler) 91 | self.missionRaw = MissionRaw(address: address, port: port, scheduler: scheduler) 92 | self.mocap = Mocap(address: address, port: port, scheduler: scheduler) 93 | self.offboard = Offboard(address: address, port: port, scheduler: scheduler) 94 | self.param = Param(address: address, port: port, scheduler: scheduler) 95 | self.rtk = Rtk(address: address, port: port, scheduler: scheduler) 96 | self.shell = Shell(address: address, port: port, scheduler: scheduler) 97 | self.telemetry = Telemetry(address: address, port: port, scheduler: scheduler) 98 | self.transponder = Transponder(address: address, port: port, scheduler: scheduler) 99 | self.tune = Tune(address: address, port: port, scheduler: scheduler) 100 | } 101 | 102 | public func disconnect() { 103 | mavsdkServer?.stop() 104 | mavsdkServer = nil 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MAVSDK 2 | 3 | The official MAVSDK client for Swift. This cross-platform gRPC library communicates to MAVLink compatible systems using a plugin architecture. 4 | 5 | ## Installing 6 | 7 | ### Swift Package 8 | 9 | Add the following to your Package.swift dependencies: 10 | ``` 11 | dependencies: [ 12 | .package(url: "https://github.com/mavlink/mavsdk-swift", from: "1.0.1"), 13 | ], 14 | ``` 15 | And add each product within each target as needed (`MavsdkServer` may be optional): 16 | ``` 17 | targets: [ 18 | .target(name: "MyTarget", 19 | dependencies: [ 20 | .product(name: "Mavsdk", package: "Mavsdk"), 21 | .product(name: "MavsdkServer", package: "Mavsdk") 22 | ], 23 | ), 24 | ] 25 | ``` 26 | 27 | ### Start MAVLink connection 28 | 29 | The steps below assume that your iOS device has a network connection to the drone, such as WiFi. 30 | 31 | By default, the SDK will connect using MAVLink on UDP port 14540 to match the default port of the PX4 SITL (software in the loop simulation) drone. 32 | 33 | The backend is currently limited to UDP only, even though the core supports UDP, TCP, and serial. 34 | 35 | ```swift 36 | import MavsdkServer 37 | import Mavsdk 38 | 39 | let port = mavsdkServer.run() 40 | let drone = Drone(port: Int32(port)) 41 | ``` 42 | 43 | After that, you can start writing some code [as described below](#start-writing-code). 44 | 45 | __For advanced users:__ note that `mavsdkServer.run()` will run the SDK backend on a background thread on the iOS device. You could use `Drone(address:port:scheduler)` connect the SDK to another backend IP address and port (such as `192.168.0.42`) and running 46 | ```swift 47 | let drone = Drone(address: "192.168.0.42", port: 50051) 48 | ``` 49 | 50 | ## Start writing code 51 | After that, you can start using the SDK, for instance: 52 | 53 | ```swift 54 | _ = drone.action.arm() 55 | .subscribe(onCompleted: { 56 | drone.action.takeoff() 57 | }, onError: { error in 58 | print(error.localizedDescription) 59 | }) 60 | ``` 61 | 62 | or 63 | 64 | ```swift 65 | _ = drone.telemetry.position 66 | .subscribe(onNext: { position in 67 | print(position) 68 | }, onError: { error in 69 | print(error.localizedDescription) 70 | }) 71 | ``` 72 | 73 | You can learn more about [RxSwift](https://github.com/ReactiveX/RxSwift), and check out [MAVSDK-Swift-Example](https://github.com/mavlink/MAVSDK-Swift-Example) for more information on using this framework. 74 | 75 | ## Contribute 76 | 77 | Before contributing, it's a good idea to file an issue on GitHub to get feedback from the project maintainers. 78 | 79 | ### Build the SDK 80 | 81 | MAVSDK functions are mainly generated from files in the _/proto_ submodule (see _Sources/Mavsdk/proto_). First, you may need to initialize any uninitialized and nested submodules. 82 | 83 | ```shell 84 | git submodule update --init --recursive 85 | ``` 86 | 87 | Before building the SDK you may need to install the following packages via [Homebrew](https://brew.sh/). 88 | 89 | ```shell 90 | brew install protobuf 91 | ``` 92 | 93 | You will also need to install the following [Python](https://www.python.org/) libraries for MAVSDK. The first two commands are optional, and the last is required. 94 | 95 | ```shell 96 | python3 -m venv venv 97 | source venv/bin/activate 98 | 99 | pip3 install protoc-gen-mavsdk 100 | ``` 101 | 102 | Then, to generate the source code, run: 103 | 104 | ```shell 105 | bash Sources/Mavsdk/tools/generate_from_protos.bash 106 | ``` 107 | 108 | **NOTE**: The following requires Xcode 12 and Swift 5.3. 109 | 110 | With your current Xcode project open, you can then locally source `Mavsdk` to override the remote Swift Package into your project. Open a Finder window, drag-and-drop the `Mavsdk` directory within the top level of your .xcodeproj, then click `File > Swift Packages > Resolve Package Versions` to resolve the package dependencies. 111 | 112 | **NOTE**: If you have Xcode 11 and Swift 5.2 or lower and require `MavsdkServer`, use these additional steps. 113 | 114 | Move `MavsdkServer.swift` from within the Mavsdk package into your main project. Modify Package.swift to remove the following: 115 | ``` 116 | .library(name: "MavsdkServer", 117 | targets: [ 118 | "mavsdk_server" 119 | ] 120 | ) 121 | ``` 122 | 123 | Next, using Finder, download, unzip and move the binary for the iOS MAVSDK server (`mavsdk_server.xcframework`) downloaded from [MAVSDK Releases](https://github.com/mavlink/MAVSDK/releases) into your projects root directory (or where other dependencies may be installed) and update `FRAMEWORK_SEARCH_PATHS` in the Target Build Settings accordingly to find it. 124 | 125 | ### Generate docs 126 | 127 | **Note**: CI generates docs for the main branch and pushes them to a [s3 bucket](http://dronecode-sdk-swift.s3.eu-central-1.amazonaws.com/docs/index.html). 128 | 129 | To test the doc generation locally, install [jazzy](https://github.com/realm/jazzy): 130 | 131 | ``` 132 | sudo gem install jazzy 133 | ``` 134 | 135 | Then, to generate the docs, run: 136 | ``` 137 | bash Sources/Mavsdk/tools/generate_docs.sh 138 | ``` 139 | -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/Core.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import RxSwift 3 | import GRPC 4 | import NIO 5 | 6 | /** 7 | Access to the connection state and core configurations 8 | */ 9 | public class Core { 10 | private let service: Mavsdk_Rpc_Core_CoreServiceClient 11 | private let scheduler: SchedulerType 12 | private let clientEventLoopGroup: EventLoopGroup 13 | 14 | /** 15 | Initializes a new `Core` plugin. 16 | 17 | Normally never created manually, but used from the `Drone` helper class instead. 18 | 19 | - Parameters: 20 | - address: The address of the `MavsdkServer` instance to connect to 21 | - port: The port of the `MavsdkServer` instance to connect to 22 | - scheduler: The scheduler to be used by `Observable`s 23 | */ 24 | public convenience init(address: String = "localhost", 25 | port: Int32 = 50051, 26 | scheduler: SchedulerType = ConcurrentDispatchQueueScheduler(qos: .background)) { 27 | let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 2) 28 | let channel = ClientConnection.insecure(group: eventLoopGroup).connect(host: address, port: Int(port)) 29 | let service = Mavsdk_Rpc_Core_CoreServiceClient(channel: channel) 30 | 31 | self.init(service: service, scheduler: scheduler, eventLoopGroup: eventLoopGroup) 32 | } 33 | 34 | init(service: Mavsdk_Rpc_Core_CoreServiceClient, scheduler: SchedulerType, eventLoopGroup: EventLoopGroup) { 35 | self.service = service 36 | self.scheduler = scheduler 37 | self.clientEventLoopGroup = eventLoopGroup 38 | } 39 | 40 | public struct RuntimeCoreError: Error { 41 | public let description: String 42 | 43 | init(_ description: String) { 44 | self.description = description 45 | } 46 | } 47 | 48 | 49 | 50 | 51 | /** 52 | Connection state type. 53 | */ 54 | public struct ConnectionState: Equatable { 55 | public let isConnected: Bool 56 | 57 | 58 | 59 | /** 60 | Initializes a new `ConnectionState`. 61 | 62 | 63 | - Parameter isConnected: Whether the vehicle got connected or disconnected 64 | 65 | */ 66 | public init(isConnected: Bool) { 67 | self.isConnected = isConnected 68 | } 69 | 70 | internal var rpcConnectionState: Mavsdk_Rpc_Core_ConnectionState { 71 | var rpcConnectionState = Mavsdk_Rpc_Core_ConnectionState() 72 | 73 | 74 | rpcConnectionState.isConnected = isConnected 75 | 76 | 77 | 78 | return rpcConnectionState 79 | } 80 | 81 | internal static func translateFromRpc(_ rpcConnectionState: Mavsdk_Rpc_Core_ConnectionState) -> ConnectionState { 82 | return ConnectionState(isConnected: rpcConnectionState.isConnected) 83 | } 84 | 85 | public static func == (lhs: ConnectionState, rhs: ConnectionState) -> Bool { 86 | return lhs.isConnected == rhs.isConnected 87 | } 88 | } 89 | 90 | 91 | 92 | /** 93 | Subscribe to 'connection state' updates. 94 | */ 95 | public lazy var connectionState: Observable = createConnectionStateObservable() 96 | 97 | 98 | 99 | private func createConnectionStateObservable() -> Observable { 100 | return Observable.create { [unowned self] observer in 101 | let request = Mavsdk_Rpc_Core_SubscribeConnectionStateRequest() 102 | 103 | 104 | 105 | let serverStreamingCall = self.service.subscribeConnectionState(request, handler: { (response) in 106 | 107 | 108 | 109 | let connectionState = ConnectionState.translateFromRpc(response.connectionState) 110 | 111 | 112 | 113 | observer.onNext(connectionState) 114 | 115 | }) 116 | 117 | return Disposables.create { 118 | serverStreamingCall.cancel(promise: nil) 119 | } 120 | } 121 | .retry { error in 122 | error.map { 123 | guard $0 is RuntimeCoreError else { throw $0 } 124 | } 125 | } 126 | .share(replay: 1) 127 | } 128 | 129 | /** 130 | Set timeout of MAVLink transfers. 131 | 132 | The default timeout used is generally (0.5 seconds) seconds. 133 | If MAVSDK is used on the same host this timeout can be reduced, while 134 | if MAVSDK has to communicate over links with high latency it might 135 | need to be increased to prevent timeouts. 136 | 137 | - Parameter timeoutS: Timeout in seconds 138 | 139 | */ 140 | public func setMavlinkTimeout(timeoutS: Double) -> Completable { 141 | return Completable.create { completable in 142 | var request = Mavsdk_Rpc_Core_SetMavlinkTimeoutRequest() 143 | 144 | 145 | 146 | request.timeoutS = timeoutS 147 | 148 | 149 | 150 | do { 151 | 152 | let _ = try self.service.setMavlinkTimeout(request) 153 | completable(.completed) 154 | 155 | } catch { 156 | completable(.error(error)) 157 | } 158 | 159 | return Disposables.create() 160 | } 161 | } 162 | } -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/rtk.grpc.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DO NOT EDIT. 3 | // 4 | // Generated by the protocol buffer compiler. 5 | // Source: rtk.proto 6 | // 7 | 8 | // 9 | // Copyright 2018, gRPC Authors All rights reserved. 10 | // 11 | // Licensed under the Apache License, Version 2.0 (the "License"); 12 | // you may not use this file except in compliance with the License. 13 | // You may obtain a copy of the License at 14 | // 15 | // http://www.apache.org/licenses/LICENSE-2.0 16 | // 17 | // Unless required by applicable law or agreed to in writing, software 18 | // distributed under the License is distributed on an "AS IS" BASIS, 19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | // See the License for the specific language governing permissions and 21 | // limitations under the License. 22 | // 23 | import GRPC 24 | import NIO 25 | import SwiftProtobuf 26 | 27 | 28 | /// Service to send RTK corrections to the vehicle. 29 | /// 30 | /// Usage: instantiate `Mavsdk_Rpc_Rtk_RtkServiceClient`, then call methods of this protocol to make API calls. 31 | internal protocol Mavsdk_Rpc_Rtk_RtkServiceClientProtocol: GRPCClient { 32 | var serviceName: String { get } 33 | var interceptors: Mavsdk_Rpc_Rtk_RtkServiceClientInterceptorFactoryProtocol? { get } 34 | 35 | func sendRtcmData( 36 | _ request: Mavsdk_Rpc_Rtk_SendRtcmDataRequest, 37 | callOptions: CallOptions? 38 | ) -> UnaryCall 39 | } 40 | 41 | extension Mavsdk_Rpc_Rtk_RtkServiceClientProtocol { 42 | internal var serviceName: String { 43 | return "mavsdk.rpc.rtk.RtkService" 44 | } 45 | 46 | /// Send RTCM data. 47 | /// 48 | /// - Parameters: 49 | /// - request: Request to send to SendRtcmData. 50 | /// - callOptions: Call options. 51 | /// - Returns: A `UnaryCall` with futures for the metadata, status and response. 52 | internal func sendRtcmData( 53 | _ request: Mavsdk_Rpc_Rtk_SendRtcmDataRequest, 54 | callOptions: CallOptions? = nil 55 | ) -> UnaryCall { 56 | return self.makeUnaryCall( 57 | path: "/mavsdk.rpc.rtk.RtkService/SendRtcmData", 58 | request: request, 59 | callOptions: callOptions ?? self.defaultCallOptions, 60 | interceptors: self.interceptors?.makeSendRtcmDataInterceptors() ?? [] 61 | ) 62 | } 63 | } 64 | 65 | internal protocol Mavsdk_Rpc_Rtk_RtkServiceClientInterceptorFactoryProtocol { 66 | 67 | /// - Returns: Interceptors to use when invoking 'sendRtcmData'. 68 | func makeSendRtcmDataInterceptors() -> [ClientInterceptor] 69 | } 70 | 71 | internal final class Mavsdk_Rpc_Rtk_RtkServiceClient: Mavsdk_Rpc_Rtk_RtkServiceClientProtocol { 72 | internal let channel: GRPCChannel 73 | internal var defaultCallOptions: CallOptions 74 | internal var interceptors: Mavsdk_Rpc_Rtk_RtkServiceClientInterceptorFactoryProtocol? 75 | 76 | /// Creates a client for the mavsdk.rpc.rtk.RtkService service. 77 | /// 78 | /// - Parameters: 79 | /// - channel: `GRPCChannel` to the service host. 80 | /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. 81 | /// - interceptors: A factory providing interceptors for each RPC. 82 | internal init( 83 | channel: GRPCChannel, 84 | defaultCallOptions: CallOptions = CallOptions(), 85 | interceptors: Mavsdk_Rpc_Rtk_RtkServiceClientInterceptorFactoryProtocol? = nil 86 | ) { 87 | self.channel = channel 88 | self.defaultCallOptions = defaultCallOptions 89 | self.interceptors = interceptors 90 | } 91 | } 92 | 93 | /// Service to send RTK corrections to the vehicle. 94 | /// 95 | /// To build a server, implement a class that conforms to this protocol. 96 | internal protocol Mavsdk_Rpc_Rtk_RtkServiceProvider: CallHandlerProvider { 97 | var interceptors: Mavsdk_Rpc_Rtk_RtkServiceServerInterceptorFactoryProtocol? { get } 98 | 99 | /// Send RTCM data. 100 | func sendRtcmData(request: Mavsdk_Rpc_Rtk_SendRtcmDataRequest, context: StatusOnlyCallContext) -> EventLoopFuture 101 | } 102 | 103 | extension Mavsdk_Rpc_Rtk_RtkServiceProvider { 104 | internal var serviceName: Substring { return "mavsdk.rpc.rtk.RtkService" } 105 | 106 | /// Determines, calls and returns the appropriate request handler, depending on the request's method. 107 | /// Returns nil for methods not handled by this service. 108 | internal func handle( 109 | method name: Substring, 110 | context: CallHandlerContext 111 | ) -> GRPCServerHandlerProtocol? { 112 | switch name { 113 | case "SendRtcmData": 114 | return UnaryServerHandler( 115 | context: context, 116 | requestDeserializer: ProtobufDeserializer(), 117 | responseSerializer: ProtobufSerializer(), 118 | interceptors: self.interceptors?.makeSendRtcmDataInterceptors() ?? [], 119 | userFunction: self.sendRtcmData(request:context:) 120 | ) 121 | 122 | default: 123 | return nil 124 | } 125 | } 126 | } 127 | 128 | internal protocol Mavsdk_Rpc_Rtk_RtkServiceServerInterceptorFactoryProtocol { 129 | 130 | /// - Returns: Interceptors to use when handling 'sendRtcmData'. 131 | /// Defaults to calling `self.makeInterceptors()`. 132 | func makeSendRtcmDataInterceptors() -> [ServerInterceptor] 133 | } 134 | -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/tune.grpc.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DO NOT EDIT. 3 | // 4 | // Generated by the protocol buffer compiler. 5 | // Source: tune.proto 6 | // 7 | 8 | // 9 | // Copyright 2018, gRPC Authors All rights reserved. 10 | // 11 | // Licensed under the Apache License, Version 2.0 (the "License"); 12 | // you may not use this file except in compliance with the License. 13 | // You may obtain a copy of the License at 14 | // 15 | // http://www.apache.org/licenses/LICENSE-2.0 16 | // 17 | // Unless required by applicable law or agreed to in writing, software 18 | // distributed under the License is distributed on an "AS IS" BASIS, 19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | // See the License for the specific language governing permissions and 21 | // limitations under the License. 22 | // 23 | import GRPC 24 | import NIO 25 | import SwiftProtobuf 26 | 27 | 28 | /// Enable creating and sending a tune to be played on the system. 29 | /// 30 | /// Usage: instantiate `Mavsdk_Rpc_Tune_TuneServiceClient`, then call methods of this protocol to make API calls. 31 | internal protocol Mavsdk_Rpc_Tune_TuneServiceClientProtocol: GRPCClient { 32 | var serviceName: String { get } 33 | var interceptors: Mavsdk_Rpc_Tune_TuneServiceClientInterceptorFactoryProtocol? { get } 34 | 35 | func playTune( 36 | _ request: Mavsdk_Rpc_Tune_PlayTuneRequest, 37 | callOptions: CallOptions? 38 | ) -> UnaryCall 39 | } 40 | 41 | extension Mavsdk_Rpc_Tune_TuneServiceClientProtocol { 42 | internal var serviceName: String { 43 | return "mavsdk.rpc.tune.TuneService" 44 | } 45 | 46 | /// Send a tune to be played by the system. 47 | /// 48 | /// - Parameters: 49 | /// - request: Request to send to PlayTune. 50 | /// - callOptions: Call options. 51 | /// - Returns: A `UnaryCall` with futures for the metadata, status and response. 52 | internal func playTune( 53 | _ request: Mavsdk_Rpc_Tune_PlayTuneRequest, 54 | callOptions: CallOptions? = nil 55 | ) -> UnaryCall { 56 | return self.makeUnaryCall( 57 | path: "/mavsdk.rpc.tune.TuneService/PlayTune", 58 | request: request, 59 | callOptions: callOptions ?? self.defaultCallOptions, 60 | interceptors: self.interceptors?.makePlayTuneInterceptors() ?? [] 61 | ) 62 | } 63 | } 64 | 65 | internal protocol Mavsdk_Rpc_Tune_TuneServiceClientInterceptorFactoryProtocol { 66 | 67 | /// - Returns: Interceptors to use when invoking 'playTune'. 68 | func makePlayTuneInterceptors() -> [ClientInterceptor] 69 | } 70 | 71 | internal final class Mavsdk_Rpc_Tune_TuneServiceClient: Mavsdk_Rpc_Tune_TuneServiceClientProtocol { 72 | internal let channel: GRPCChannel 73 | internal var defaultCallOptions: CallOptions 74 | internal var interceptors: Mavsdk_Rpc_Tune_TuneServiceClientInterceptorFactoryProtocol? 75 | 76 | /// Creates a client for the mavsdk.rpc.tune.TuneService service. 77 | /// 78 | /// - Parameters: 79 | /// - channel: `GRPCChannel` to the service host. 80 | /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. 81 | /// - interceptors: A factory providing interceptors for each RPC. 82 | internal init( 83 | channel: GRPCChannel, 84 | defaultCallOptions: CallOptions = CallOptions(), 85 | interceptors: Mavsdk_Rpc_Tune_TuneServiceClientInterceptorFactoryProtocol? = nil 86 | ) { 87 | self.channel = channel 88 | self.defaultCallOptions = defaultCallOptions 89 | self.interceptors = interceptors 90 | } 91 | } 92 | 93 | /// Enable creating and sending a tune to be played on the system. 94 | /// 95 | /// To build a server, implement a class that conforms to this protocol. 96 | internal protocol Mavsdk_Rpc_Tune_TuneServiceProvider: CallHandlerProvider { 97 | var interceptors: Mavsdk_Rpc_Tune_TuneServiceServerInterceptorFactoryProtocol? { get } 98 | 99 | /// Send a tune to be played by the system. 100 | func playTune(request: Mavsdk_Rpc_Tune_PlayTuneRequest, context: StatusOnlyCallContext) -> EventLoopFuture 101 | } 102 | 103 | extension Mavsdk_Rpc_Tune_TuneServiceProvider { 104 | internal var serviceName: Substring { return "mavsdk.rpc.tune.TuneService" } 105 | 106 | /// Determines, calls and returns the appropriate request handler, depending on the request's method. 107 | /// Returns nil for methods not handled by this service. 108 | internal func handle( 109 | method name: Substring, 110 | context: CallHandlerContext 111 | ) -> GRPCServerHandlerProtocol? { 112 | switch name { 113 | case "PlayTune": 114 | return UnaryServerHandler( 115 | context: context, 116 | requestDeserializer: ProtobufDeserializer(), 117 | responseSerializer: ProtobufSerializer(), 118 | interceptors: self.interceptors?.makePlayTuneInterceptors() ?? [], 119 | userFunction: self.playTune(request:context:) 120 | ) 121 | 122 | default: 123 | return nil 124 | } 125 | } 126 | } 127 | 128 | internal protocol Mavsdk_Rpc_Tune_TuneServiceServerInterceptorFactoryProtocol { 129 | 130 | /// - Returns: Interceptors to use when handling 'playTune'. 131 | /// Defaults to calling `self.makeInterceptors()`. 132 | func makePlayTuneInterceptors() -> [ServerInterceptor] 133 | } 134 | -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/failure.grpc.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DO NOT EDIT. 3 | // 4 | // Generated by the protocol buffer compiler. 5 | // Source: failure.proto 6 | // 7 | 8 | // 9 | // Copyright 2018, gRPC Authors All rights reserved. 10 | // 11 | // Licensed under the Apache License, Version 2.0 (the "License"); 12 | // you may not use this file except in compliance with the License. 13 | // You may obtain a copy of the License at 14 | // 15 | // http://www.apache.org/licenses/LICENSE-2.0 16 | // 17 | // Unless required by applicable law or agreed to in writing, software 18 | // distributed under the License is distributed on an "AS IS" BASIS, 19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | // See the License for the specific language governing permissions and 21 | // limitations under the License. 22 | // 23 | import GRPC 24 | import NIO 25 | import SwiftProtobuf 26 | 27 | 28 | /// Inject failures into system to test failsafes. 29 | /// 30 | /// Usage: instantiate `Mavsdk_Rpc_Failure_FailureServiceClient`, then call methods of this protocol to make API calls. 31 | internal protocol Mavsdk_Rpc_Failure_FailureServiceClientProtocol: GRPCClient { 32 | var serviceName: String { get } 33 | var interceptors: Mavsdk_Rpc_Failure_FailureServiceClientInterceptorFactoryProtocol? { get } 34 | 35 | func inject( 36 | _ request: Mavsdk_Rpc_Failure_InjectRequest, 37 | callOptions: CallOptions? 38 | ) -> UnaryCall 39 | } 40 | 41 | extension Mavsdk_Rpc_Failure_FailureServiceClientProtocol { 42 | internal var serviceName: String { 43 | return "mavsdk.rpc.failure.FailureService" 44 | } 45 | 46 | /// Injects a failure. 47 | /// 48 | /// - Parameters: 49 | /// - request: Request to send to Inject. 50 | /// - callOptions: Call options. 51 | /// - Returns: A `UnaryCall` with futures for the metadata, status and response. 52 | internal func inject( 53 | _ request: Mavsdk_Rpc_Failure_InjectRequest, 54 | callOptions: CallOptions? = nil 55 | ) -> UnaryCall { 56 | return self.makeUnaryCall( 57 | path: "/mavsdk.rpc.failure.FailureService/Inject", 58 | request: request, 59 | callOptions: callOptions ?? self.defaultCallOptions, 60 | interceptors: self.interceptors?.makeInjectInterceptors() ?? [] 61 | ) 62 | } 63 | } 64 | 65 | internal protocol Mavsdk_Rpc_Failure_FailureServiceClientInterceptorFactoryProtocol { 66 | 67 | /// - Returns: Interceptors to use when invoking 'inject'. 68 | func makeInjectInterceptors() -> [ClientInterceptor] 69 | } 70 | 71 | internal final class Mavsdk_Rpc_Failure_FailureServiceClient: Mavsdk_Rpc_Failure_FailureServiceClientProtocol { 72 | internal let channel: GRPCChannel 73 | internal var defaultCallOptions: CallOptions 74 | internal var interceptors: Mavsdk_Rpc_Failure_FailureServiceClientInterceptorFactoryProtocol? 75 | 76 | /// Creates a client for the mavsdk.rpc.failure.FailureService service. 77 | /// 78 | /// - Parameters: 79 | /// - channel: `GRPCChannel` to the service host. 80 | /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. 81 | /// - interceptors: A factory providing interceptors for each RPC. 82 | internal init( 83 | channel: GRPCChannel, 84 | defaultCallOptions: CallOptions = CallOptions(), 85 | interceptors: Mavsdk_Rpc_Failure_FailureServiceClientInterceptorFactoryProtocol? = nil 86 | ) { 87 | self.channel = channel 88 | self.defaultCallOptions = defaultCallOptions 89 | self.interceptors = interceptors 90 | } 91 | } 92 | 93 | /// Inject failures into system to test failsafes. 94 | /// 95 | /// To build a server, implement a class that conforms to this protocol. 96 | internal protocol Mavsdk_Rpc_Failure_FailureServiceProvider: CallHandlerProvider { 97 | var interceptors: Mavsdk_Rpc_Failure_FailureServiceServerInterceptorFactoryProtocol? { get } 98 | 99 | /// Injects a failure. 100 | func inject(request: Mavsdk_Rpc_Failure_InjectRequest, context: StatusOnlyCallContext) -> EventLoopFuture 101 | } 102 | 103 | extension Mavsdk_Rpc_Failure_FailureServiceProvider { 104 | internal var serviceName: Substring { return "mavsdk.rpc.failure.FailureService" } 105 | 106 | /// Determines, calls and returns the appropriate request handler, depending on the request's method. 107 | /// Returns nil for methods not handled by this service. 108 | internal func handle( 109 | method name: Substring, 110 | context: CallHandlerContext 111 | ) -> GRPCServerHandlerProtocol? { 112 | switch name { 113 | case "Inject": 114 | return UnaryServerHandler( 115 | context: context, 116 | requestDeserializer: ProtobufDeserializer(), 117 | responseSerializer: ProtobufSerializer(), 118 | interceptors: self.interceptors?.makeInjectInterceptors() ?? [], 119 | userFunction: self.inject(request:context:) 120 | ) 121 | 122 | default: 123 | return nil 124 | } 125 | } 126 | } 127 | 128 | internal protocol Mavsdk_Rpc_Failure_FailureServiceServerInterceptorFactoryProtocol { 129 | 130 | /// - Returns: Interceptors to use when handling 'inject'. 131 | /// Defaults to calling `self.makeInterceptors()`. 132 | func makeInjectInterceptors() -> [ServerInterceptor] 133 | } 134 | -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/server_utility.grpc.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DO NOT EDIT. 3 | // 4 | // Generated by the protocol buffer compiler. 5 | // Source: server_utility.proto 6 | // 7 | 8 | // 9 | // Copyright 2018, gRPC Authors All rights reserved. 10 | // 11 | // Licensed under the Apache License, Version 2.0 (the "License"); 12 | // you may not use this file except in compliance with the License. 13 | // You may obtain a copy of the License at 14 | // 15 | // http://www.apache.org/licenses/LICENSE-2.0 16 | // 17 | // Unless required by applicable law or agreed to in writing, software 18 | // distributed under the License is distributed on an "AS IS" BASIS, 19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | // See the License for the specific language governing permissions and 21 | // limitations under the License. 22 | // 23 | import GRPC 24 | import NIO 25 | import SwiftProtobuf 26 | 27 | 28 | /// 29 | /// Utility for onboard MAVSDK instances for common "server" tasks. 30 | /// 31 | /// Usage: instantiate `Mavsdk_Rpc_ServerUtility_ServerUtilityServiceClient`, then call methods of this protocol to make API calls. 32 | internal protocol Mavsdk_Rpc_ServerUtility_ServerUtilityServiceClientProtocol: GRPCClient { 33 | var serviceName: String { get } 34 | var interceptors: Mavsdk_Rpc_ServerUtility_ServerUtilityServiceClientInterceptorFactoryProtocol? { get } 35 | 36 | func sendStatusText( 37 | _ request: Mavsdk_Rpc_ServerUtility_SendStatusTextRequest, 38 | callOptions: CallOptions? 39 | ) -> UnaryCall 40 | } 41 | 42 | extension Mavsdk_Rpc_ServerUtility_ServerUtilityServiceClientProtocol { 43 | internal var serviceName: String { 44 | return "mavsdk.rpc.server_utility.ServerUtilityService" 45 | } 46 | 47 | /// Sends a statustext. 48 | /// 49 | /// - Parameters: 50 | /// - request: Request to send to SendStatusText. 51 | /// - callOptions: Call options. 52 | /// - Returns: A `UnaryCall` with futures for the metadata, status and response. 53 | internal func sendStatusText( 54 | _ request: Mavsdk_Rpc_ServerUtility_SendStatusTextRequest, 55 | callOptions: CallOptions? = nil 56 | ) -> UnaryCall { 57 | return self.makeUnaryCall( 58 | path: "/mavsdk.rpc.server_utility.ServerUtilityService/SendStatusText", 59 | request: request, 60 | callOptions: callOptions ?? self.defaultCallOptions, 61 | interceptors: self.interceptors?.makeSendStatusTextInterceptors() ?? [] 62 | ) 63 | } 64 | } 65 | 66 | internal protocol Mavsdk_Rpc_ServerUtility_ServerUtilityServiceClientInterceptorFactoryProtocol { 67 | 68 | /// - Returns: Interceptors to use when invoking 'sendStatusText'. 69 | func makeSendStatusTextInterceptors() -> [ClientInterceptor] 70 | } 71 | 72 | internal final class Mavsdk_Rpc_ServerUtility_ServerUtilityServiceClient: Mavsdk_Rpc_ServerUtility_ServerUtilityServiceClientProtocol { 73 | internal let channel: GRPCChannel 74 | internal var defaultCallOptions: CallOptions 75 | internal var interceptors: Mavsdk_Rpc_ServerUtility_ServerUtilityServiceClientInterceptorFactoryProtocol? 76 | 77 | /// Creates a client for the mavsdk.rpc.server_utility.ServerUtilityService service. 78 | /// 79 | /// - Parameters: 80 | /// - channel: `GRPCChannel` to the service host. 81 | /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. 82 | /// - interceptors: A factory providing interceptors for each RPC. 83 | internal init( 84 | channel: GRPCChannel, 85 | defaultCallOptions: CallOptions = CallOptions(), 86 | interceptors: Mavsdk_Rpc_ServerUtility_ServerUtilityServiceClientInterceptorFactoryProtocol? = nil 87 | ) { 88 | self.channel = channel 89 | self.defaultCallOptions = defaultCallOptions 90 | self.interceptors = interceptors 91 | } 92 | } 93 | 94 | /// 95 | /// Utility for onboard MAVSDK instances for common "server" tasks. 96 | /// 97 | /// To build a server, implement a class that conforms to this protocol. 98 | internal protocol Mavsdk_Rpc_ServerUtility_ServerUtilityServiceProvider: CallHandlerProvider { 99 | var interceptors: Mavsdk_Rpc_ServerUtility_ServerUtilityServiceServerInterceptorFactoryProtocol? { get } 100 | 101 | /// Sends a statustext. 102 | func sendStatusText(request: Mavsdk_Rpc_ServerUtility_SendStatusTextRequest, context: StatusOnlyCallContext) -> EventLoopFuture 103 | } 104 | 105 | extension Mavsdk_Rpc_ServerUtility_ServerUtilityServiceProvider { 106 | internal var serviceName: Substring { return "mavsdk.rpc.server_utility.ServerUtilityService" } 107 | 108 | /// Determines, calls and returns the appropriate request handler, depending on the request's method. 109 | /// Returns nil for methods not handled by this service. 110 | internal func handle( 111 | method name: Substring, 112 | context: CallHandlerContext 113 | ) -> GRPCServerHandlerProtocol? { 114 | switch name { 115 | case "SendStatusText": 116 | return UnaryServerHandler( 117 | context: context, 118 | requestDeserializer: ProtobufDeserializer(), 119 | responseSerializer: ProtobufSerializer(), 120 | interceptors: self.interceptors?.makeSendStatusTextInterceptors() ?? [], 121 | userFunction: self.sendStatusText(request:context:) 122 | ) 123 | 124 | default: 125 | return nil 126 | } 127 | } 128 | } 129 | 130 | internal protocol Mavsdk_Rpc_ServerUtility_ServerUtilityServiceServerInterceptorFactoryProtocol { 131 | 132 | /// - Returns: Interceptors to use when handling 'sendStatusText'. 133 | /// Defaults to calling `self.makeInterceptors()`. 134 | func makeSendStatusTextInterceptors() -> [ServerInterceptor] 135 | } 136 | -------------------------------------------------------------------------------- /Tests/MavsdkTests/CoreTest.swift: -------------------------------------------------------------------------------- 1 | //import Foundation 2 | //import RxBlocking 3 | //import RxSwift 4 | //import RxTest 5 | //import XCTest 6 | //@testable import Mavsdk 7 | // 8 | //class CoreTest: XCTestCase { 9 | // let ARBITRARY_UUID: UInt64 = 42 10 | // let ARBITRARY_PLUGIN_NAME: String = "action" 11 | // let ARBITRARY_PLUGIN_ADDRESS: String = "localhost" 12 | // let ARBITRARY_PLUGIN_PORT: Int32 = 1291 13 | // 14 | // func testConnectionStateObservableEmitsNothingWhenNoEvent() { 15 | // let fakeService = Mavsdk_Rpc_Core_CoreServiceServiceTestStub() 16 | // let fakeCall = Mavsdk_Rpc_Core_CoreServiceSubscribeConnectionStateCallTestStub() 17 | // fakeService.subscribeConnectionStateCalls.append(fakeCall) 18 | // 19 | // let scheduler = TestScheduler(initialClock: 0) 20 | // let client = Core(service: fakeService, scheduler: scheduler) 21 | // let observer = scheduler.createObserver(Core.ConnectionState.self) 22 | // 23 | // let _ = client.connectionState.subscribe(observer) 24 | // scheduler.start() 25 | // 26 | // XCTAssertTrue(observer.events.isEmpty) 27 | // } 28 | // 29 | // func testConnectionStateObservableReceivesOneEvent() { 30 | // let fakeService = Mavsdk_Rpc_Core_CoreServiceServiceTestStub() 31 | // let fakeCall = Mavsdk_Rpc_Core_CoreServiceSubscribeConnectionStateCallTestStub() 32 | // 33 | // let expectedConnectionState = Core.ConnectionState(uuid: ARBITRARY_UUID, isConnected: true) 34 | // fakeCall.outputs = [createConnectionStateResponse(connectionState: expectedConnectionState)] 35 | // fakeService.subscribeConnectionStateCalls.append(fakeCall) 36 | // 37 | // let scheduler = TestScheduler(initialClock: 0) 38 | // let client = Core(service: fakeService, scheduler: scheduler) 39 | // let observer = scheduler.createObserver(Core.ConnectionState.self) 40 | // 41 | // let _ = client.connectionState.subscribe(observer) 42 | // scheduler.start() 43 | // 44 | // let expectedEvents = [ 45 | // next(0, expectedConnectionState), 46 | // ] 47 | // 48 | // XCTAssertEqual(expectedEvents.count, observer.events.count) 49 | // XCTAssertTrue(observer.events.elementsEqual(expectedEvents, by: { (observed, expected) in 50 | // observed.value == expected.value 51 | // })) 52 | // } 53 | // 54 | // func createConnectionStateResponse(connectionState: Core.ConnectionState) -> Mavsdk_Rpc_Core_ConnectionStateResponse { 55 | // var response = Mavsdk_Rpc_Core_ConnectionStateResponse() 56 | // response.connectionState.uuid = connectionState.uuid 57 | // response.connectionState.isConnected = connectionState.isConnected 58 | // 59 | // return response 60 | // } 61 | // 62 | // func testDiscoverObservableReceivesMultipleEvents() { 63 | // let fakeService = Mavsdk_Rpc_Core_CoreServiceServiceTestStub() 64 | // let fakeCall = Mavsdk_Rpc_Core_CoreServiceSubscribeConnectionStateCallTestStub() 65 | // 66 | // fakeCall.outputs = [] 67 | // var expectedConnectionStates = [Core.ConnectionState]() 68 | // expectedConnectionStates.append(Core.ConnectionState(uuid: 4352334, isConnected: false)) 69 | // expectedConnectionStates.append(Core.ConnectionState(uuid: 213534, isConnected: true)) 70 | // expectedConnectionStates.append(Core.ConnectionState(uuid: 12, isConnected: false)) 71 | // expectedConnectionStates.append(Core.ConnectionState(uuid: 9985232, isConnected: false)) 72 | // expectedConnectionStates.append(Core.ConnectionState(uuid: 1872358, isConnected: true)) 73 | // 74 | // for expectedConnectionState in expectedConnectionStates { 75 | // fakeCall.outputs.append(createConnectionStateResponse(connectionState: expectedConnectionState)) 76 | // } 77 | // fakeService.subscribeConnectionStateCalls.append(fakeCall) 78 | // 79 | // let scheduler = TestScheduler(initialClock: 0) 80 | // let client = Core(service: fakeService, scheduler: scheduler) 81 | // let observer = scheduler.createObserver(Core.ConnectionState.self) 82 | // 83 | // let _ = client.connectionState.subscribe(observer) 84 | // scheduler.start() 85 | // 86 | // XCTAssertEqual(expectedConnectionStates.count, observer.events.count) 87 | // XCTAssertTrue(observer.events.elementsEqual(expectedConnectionStates.map({ connState in next(1, connState) }), by: { (observed, expected) in observed.value == expected.value})) 88 | // } 89 | // 90 | // func testListRunningPluginsEmitsNothingWhenEmpty() { 91 | // let fakeService = Mavsdk_Rpc_Core_CoreServiceServiceTestStub() 92 | // fakeService.listRunningPluginsResponses.append(Mavsdk_Rpc_Core_ListRunningPluginsResponse()) 93 | // let scheduler = TestScheduler(initialClock: 0) 94 | // let client = Core(service: fakeService, scheduler: scheduler) 95 | // scheduler.start() 96 | // 97 | // let pluginInfos = try! client.listRunningPlugins().toBlocking().single() 98 | // 99 | // XCTAssertTrue(pluginInfos.isEmpty) 100 | // } 101 | // 102 | // func testListRunningPluginsEmitsOnePluginInfo() throws { 103 | // let fakeService = Mavsdk_Rpc_Core_CoreServiceServiceTestStub() 104 | // var response = Mavsdk_Rpc_Core_ListRunningPluginsResponse() 105 | // response.pluginInfo.append(createRPCPluginInfo(name: ARBITRARY_PLUGIN_NAME, address: ARBITRARY_PLUGIN_ADDRESS, port: ARBITRARY_PLUGIN_PORT)) 106 | // fakeService.listRunningPluginsResponses.append(response) 107 | // let scheduler = TestScheduler(initialClock: 0) 108 | // let client = Core(service: fakeService, scheduler: scheduler) 109 | // let expectedPluginInfo = Core.PluginInfo.translateFromRpc(response.pluginInfo[0]) 110 | // 111 | // scheduler.start() 112 | // let pluginInfos = try client.listRunningPlugins().toBlocking().single() 113 | // 114 | // XCTAssertEqual(1, pluginInfos.count) 115 | // XCTAssertEqual(expectedPluginInfo, pluginInfos.first) 116 | // } 117 | // 118 | // func createRPCPluginInfo(name: String, address: String, port: Int32) -> Mavsdk_Rpc_Core_PluginInfo { 119 | // var pluginInfo = Mavsdk_Rpc_Core_PluginInfo() 120 | // pluginInfo.name = ARBITRARY_PLUGIN_NAME 121 | // pluginInfo.address = ARBITRARY_PLUGIN_ADDRESS 122 | // pluginInfo.port = ARBITRARY_PLUGIN_PORT 123 | // 124 | // return pluginInfo 125 | // } 126 | // 127 | // func testListRunningPluginsEmitsMultiplePluginInfos() throws { 128 | // let fakeService = Mavsdk_Rpc_Core_CoreServiceServiceTestStub() 129 | // var response = Mavsdk_Rpc_Core_ListRunningPluginsResponse() 130 | // response.pluginInfo.append(createRPCPluginInfo(name: "name1", address: "add1", port: 1291)) 131 | // response.pluginInfo.append(createRPCPluginInfo(name: "name2", address: "add2", port: 1492)) 132 | // response.pluginInfo.append(createRPCPluginInfo(name: "name3", address: "add3", port: 1515)) 133 | // fakeService.listRunningPluginsResponses.append(response) 134 | // let scheduler = TestScheduler(initialClock: 0) 135 | // let client = Core(service: fakeService, scheduler: scheduler) 136 | // 137 | // scheduler.start() 138 | // let pluginInfos = try client.listRunningPlugins().toBlocking().single() 139 | // 140 | // XCTAssertEqual(pluginInfos.count, response.pluginInfo.count) 141 | // 142 | // for i in 0 ... pluginInfos.count - 1 { 143 | // XCTAssertEqual(Core.PluginInfo.translateFromRpc(response.pluginInfo[i]), pluginInfos[i]) 144 | // } 145 | // } 146 | //} 147 | -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/Rtk.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import RxSwift 3 | import GRPC 4 | import NIO 5 | 6 | /** 7 | Service to send RTK corrections to the vehicle. 8 | */ 9 | public class Rtk { 10 | private let service: Mavsdk_Rpc_Rtk_RtkServiceClient 11 | private let scheduler: SchedulerType 12 | private let clientEventLoopGroup: EventLoopGroup 13 | 14 | /** 15 | Initializes a new `Rtk` plugin. 16 | 17 | Normally never created manually, but used from the `Drone` helper class instead. 18 | 19 | - Parameters: 20 | - address: The address of the `MavsdkServer` instance to connect to 21 | - port: The port of the `MavsdkServer` instance to connect to 22 | - scheduler: The scheduler to be used by `Observable`s 23 | */ 24 | public convenience init(address: String = "localhost", 25 | port: Int32 = 50051, 26 | scheduler: SchedulerType = ConcurrentDispatchQueueScheduler(qos: .background)) { 27 | let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 2) 28 | let channel = ClientConnection.insecure(group: eventLoopGroup).connect(host: address, port: Int(port)) 29 | let service = Mavsdk_Rpc_Rtk_RtkServiceClient(channel: channel) 30 | 31 | self.init(service: service, scheduler: scheduler, eventLoopGroup: eventLoopGroup) 32 | } 33 | 34 | init(service: Mavsdk_Rpc_Rtk_RtkServiceClient, scheduler: SchedulerType, eventLoopGroup: EventLoopGroup) { 35 | self.service = service 36 | self.scheduler = scheduler 37 | self.clientEventLoopGroup = eventLoopGroup 38 | } 39 | 40 | public struct RuntimeRtkError: Error { 41 | public let description: String 42 | 43 | init(_ description: String) { 44 | self.description = description 45 | } 46 | } 47 | 48 | 49 | public struct RtkError: Error { 50 | public let code: Rtk.RtkResult.Result 51 | public let description: String 52 | } 53 | 54 | 55 | 56 | /** 57 | RTCM data type 58 | */ 59 | public struct RtcmData: Equatable { 60 | public let data: String 61 | 62 | 63 | 64 | /** 65 | Initializes a new `RtcmData`. 66 | 67 | 68 | - Parameter data: The data encoded as a string 69 | 70 | */ 71 | public init(data: String) { 72 | self.data = data 73 | } 74 | 75 | internal var rpcRtcmData: Mavsdk_Rpc_Rtk_RtcmData { 76 | var rpcRtcmData = Mavsdk_Rpc_Rtk_RtcmData() 77 | 78 | 79 | rpcRtcmData.data = data 80 | 81 | 82 | 83 | return rpcRtcmData 84 | } 85 | 86 | internal static func translateFromRpc(_ rpcRtcmData: Mavsdk_Rpc_Rtk_RtcmData) -> RtcmData { 87 | return RtcmData(data: rpcRtcmData.data) 88 | } 89 | 90 | public static func == (lhs: RtcmData, rhs: RtcmData) -> Bool { 91 | return lhs.data == rhs.data 92 | } 93 | } 94 | 95 | /** 96 | 97 | */ 98 | public struct RtkResult: Equatable { 99 | public let result: Result 100 | public let resultStr: String 101 | 102 | 103 | 104 | 105 | /** 106 | Possible results returned for rtk requests. 107 | */ 108 | public enum Result: Equatable { 109 | /// Unknown result. 110 | case unknown 111 | /// Request succeeded. 112 | case success 113 | /// Passed data is too long. 114 | case tooLong 115 | /// No system connected. 116 | case noSystem 117 | /// Connection error. 118 | case connectionError 119 | case UNRECOGNIZED(Int) 120 | 121 | internal var rpcResult: Mavsdk_Rpc_Rtk_RtkResult.Result { 122 | switch self { 123 | case .unknown: 124 | return .unknown 125 | case .success: 126 | return .success 127 | case .tooLong: 128 | return .tooLong 129 | case .noSystem: 130 | return .noSystem 131 | case .connectionError: 132 | return .connectionError 133 | case .UNRECOGNIZED(let i): 134 | return .UNRECOGNIZED(i) 135 | } 136 | } 137 | 138 | internal static func translateFromRpc(_ rpcResult: Mavsdk_Rpc_Rtk_RtkResult.Result) -> Result { 139 | switch rpcResult { 140 | case .unknown: 141 | return .unknown 142 | case .success: 143 | return .success 144 | case .tooLong: 145 | return .tooLong 146 | case .noSystem: 147 | return .noSystem 148 | case .connectionError: 149 | return .connectionError 150 | case .UNRECOGNIZED(let i): 151 | return .UNRECOGNIZED(i) 152 | } 153 | } 154 | } 155 | 156 | 157 | /** 158 | Initializes a new `RtkResult`. 159 | 160 | 161 | - Parameters: 162 | 163 | - result: Result enum value 164 | 165 | - resultStr: Human-readable English string describing the result 166 | 167 | 168 | */ 169 | public init(result: Result, resultStr: String) { 170 | self.result = result 171 | self.resultStr = resultStr 172 | } 173 | 174 | internal var rpcRtkResult: Mavsdk_Rpc_Rtk_RtkResult { 175 | var rpcRtkResult = Mavsdk_Rpc_Rtk_RtkResult() 176 | 177 | 178 | rpcRtkResult.result = result.rpcResult 179 | 180 | 181 | 182 | 183 | rpcRtkResult.resultStr = resultStr 184 | 185 | 186 | 187 | return rpcRtkResult 188 | } 189 | 190 | internal static func translateFromRpc(_ rpcRtkResult: Mavsdk_Rpc_Rtk_RtkResult) -> RtkResult { 191 | return RtkResult(result: Result.translateFromRpc(rpcRtkResult.result), resultStr: rpcRtkResult.resultStr) 192 | } 193 | 194 | public static func == (lhs: RtkResult, rhs: RtkResult) -> Bool { 195 | return lhs.result == rhs.result 196 | && lhs.resultStr == rhs.resultStr 197 | } 198 | } 199 | 200 | 201 | /** 202 | Send RTCM data. 203 | 204 | - Parameter rtcmData: The data 205 | 206 | */ 207 | public func sendRtcmData(rtcmData: RtcmData) -> Completable { 208 | return Completable.create { completable in 209 | var request = Mavsdk_Rpc_Rtk_SendRtcmDataRequest() 210 | 211 | 212 | 213 | request.rtcmData = rtcmData.rpcRtcmData 214 | 215 | 216 | 217 | do { 218 | 219 | let response = self.service.sendRtcmData(request) 220 | 221 | let result = try response.response.wait().rtkResult 222 | if (result.result == Mavsdk_Rpc_Rtk_RtkResult.Result.success) { 223 | completable(.completed) 224 | } else { 225 | completable(.error(RtkError(code: RtkResult.Result.translateFromRpc(result.result), description: result.resultStr))) 226 | } 227 | 228 | } catch { 229 | completable(.error(error)) 230 | } 231 | 232 | return Disposables.create() 233 | } 234 | } 235 | } -------------------------------------------------------------------------------- /Tests/MavsdkTests/TelemetryTest.swift: -------------------------------------------------------------------------------- 1 | import RxTest 2 | import RxSwift 3 | import RxBlocking 4 | import XCTest 5 | @testable import Mavsdk 6 | 7 | import NIO 8 | import GRPC 9 | 10 | class TelemetryTest: XCTestCase { 11 | 12 | // MARK: Subject under test 13 | 14 | var sut: Telemetry! 15 | var eventLoopGroup: MultiThreadedEventLoopGroup! 16 | var service: Mavsdk_Rpc_Telemetry_TelemetryServiceClient! 17 | var scheduler: TestScheduler! 18 | 19 | 20 | // MARK: Test lifecycle 21 | 22 | override func setUpWithError() throws { 23 | try super.setUpWithError() 24 | self.eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) 25 | 26 | let configuration = ClientConnection.Configuration( 27 | target: .hostAndPort("0.0.0.0", 0), 28 | eventLoopGroup: self.eventLoopGroup 29 | ) 30 | 31 | let channel = ClientConnection(configuration: configuration) 32 | self.service = Mavsdk_Rpc_Telemetry_TelemetryServiceClient(channel: channel) 33 | self.scheduler = TestScheduler(initialClock: 0) 34 | self.sut = Telemetry(service: service, scheduler: scheduler, eventLoopGroup: eventLoopGroup) 35 | } 36 | 37 | override func tearDownWithError() throws { 38 | self.sut = nil 39 | try self.eventLoopGroup.syncShutdownGracefully() 40 | try super.tearDownWithError() 41 | } 42 | 43 | // MARK: Test doubles 44 | 45 | // MARK: Method call expectations 46 | 47 | // MARK: Spied methods 48 | 49 | // MARK: Tests 50 | 51 | func testPositionObservableEmitsNothingWhenNoEvent() { 52 | // Given 53 | let observer = scheduler.createObserver(Telemetry.Position.self) 54 | _ = sut.position.subscribe(observer) 55 | 56 | // When 57 | scheduler.start() 58 | 59 | // Then 60 | XCTAssertEqual(0, observer.events.count) 61 | } 62 | 63 | // func testPositionObservableReceivesOneEvent() { 64 | // let position = createRPCPosition(latitudeDeg: 41.848695, longitudeDeg: 75.132751, absoluteAltitudeM: 3002.1, relativeAltitudeM: 50.3); 65 | // let positions = [position] 66 | // 67 | // checkPositionObservableReceivesEvents(positions: positions) 68 | // } 69 | // 70 | // func createRPCPosition(latitudeDeg: Double, longitudeDeg: Double, absoluteAltitudeM: Float, relativeAltitudeM: Float) -> Mavsdk_Rpc_Telemetry_Position { 71 | // var position = Mavsdk_Rpc_Telemetry_Position() 72 | // position.latitudeDeg = latitudeDeg 73 | // position.longitudeDeg = longitudeDeg 74 | // position.absoluteAltitudeM = absoluteAltitudeM 75 | // position.relativeAltitudeM = relativeAltitudeM 76 | // 77 | // return position 78 | // } 79 | // 80 | // func checkPositionObservableReceivesEvents(positions: [Mavsdk_Rpc_Telemetry_Position]) { 81 | // let fakeService = Mavsdk_Rpc_Telemetry_TelemetryServiceServiceTestStub() 82 | // let fakeCall = Mavsdk_Rpc_Telemetry_TelemetryServiceSubscribePositionCallTestStub() 83 | // 84 | // fakeCall.outputs.append(contentsOf: positions.map{ position in createPositionResponse(position: position) }) 85 | // fakeService.subscribePositionCalls.append(fakeCall) 86 | // 87 | // let scheduler = TestScheduler(initialClock: 0) 88 | // let observer = scheduler.createObserver(Telemetry.Position.self) 89 | // let telemetry = Telemetry(service: fakeService, scheduler: scheduler) 90 | // 91 | // let _ = telemetry.position.subscribe(observer) 92 | // scheduler.start() 93 | // 94 | // let expectedEvents = positions.map{ position in next(1, Telemetry.Position.translateFromRpc(position)) } 95 | // 96 | // XCTAssertEqual(expectedEvents.count, observer.events.count) 97 | // XCTAssertTrue(observer.events.elementsEqual(expectedEvents, by: { (observed, expected) in 98 | // observed.value == expected.value 99 | // })) 100 | // } 101 | // 102 | // func testPositionObservableReceivesMultipleEvents() { 103 | // var positions = [Mavsdk_Rpc_Telemetry_Position]() 104 | // positions.append(createRPCPosition(latitudeDeg: 41.848695, longitudeDeg: 75.132751, absoluteAltitudeM: 3002.1, relativeAltitudeM: 50.3)); 105 | // positions.append(createRPCPosition(latitudeDeg: 46.522626, longitudeDeg: 6.635356, absoluteAltitudeM: 542.2, relativeAltitudeM: 79.8)); 106 | // positions.append(createRPCPosition(latitudeDeg: -50.995944711358824, longitudeDeg: -72.99892046835936, absoluteAltitudeM: 1217.12, relativeAltitudeM: 2.52)); 107 | // 108 | // checkPositionObservableReceivesEvents(positions: positions) 109 | // } 110 | // 111 | // func createPositionResponse(position: Mavsdk_Rpc_Telemetry_Position) -> Mavsdk_Rpc_Telemetry_PositionResponse { 112 | // var response = Mavsdk_Rpc_Telemetry_PositionResponse() 113 | // response.position = position 114 | // 115 | // return response 116 | // } 117 | // 118 | // func testHealthObservableEmitsNothingWhenNoEvent() { 119 | // let fakeService = Mavsdk_Rpc_Telemetry_TelemetryServiceServiceTestStub() 120 | // let fakeCall = Mavsdk_Rpc_Telemetry_TelemetryServiceSubscribeHealthCallTestStub() 121 | // fakeService.subscribeHealthCalls.append(fakeCall) 122 | // 123 | // let scheduler = TestScheduler(initialClock: 0) 124 | // let telemetry = Telemetry(service: fakeService, scheduler: scheduler) 125 | // let observer = scheduler.createObserver(Telemetry.Health.self) 126 | // 127 | // let _ = telemetry.health.subscribe(observer) 128 | // scheduler.start() 129 | // 130 | // XCTAssertEqual(0, observer.events.count) 131 | // } 132 | // 133 | // func testHealthObservableReceivesOneEvent() { 134 | // checkHealthObservableReceivesEvents(nbEvents: 1) 135 | // } 136 | // 137 | // func testHealthObservableReceivesMultipleEvents() { 138 | // checkHealthObservableReceivesEvents(nbEvents: 10) 139 | // } 140 | // 141 | // func checkHealthObservableReceivesEvents(nbEvents: UInt) { 142 | // let fakeService = Mavsdk_Rpc_Telemetry_TelemetryServiceServiceTestStub() 143 | // let fakeCall = Mavsdk_Rpc_Telemetry_TelemetryServiceSubscribeHealthCallTestStub() 144 | // 145 | // var healths = [Mavsdk_Rpc_Telemetry_Health]() 146 | // for _ in 1...nbEvents { 147 | // healths.append(createRandomRPCHealth()) 148 | // } 149 | // 150 | // for health in healths { 151 | // fakeCall.outputs.append(createHealthResponse(health: health)) 152 | // } 153 | // fakeService.subscribeHealthCalls.append(fakeCall) 154 | // 155 | // let scheduler = TestScheduler(initialClock: 0) 156 | // let telemetry = Telemetry(service: fakeService, scheduler: scheduler) 157 | // let observer = scheduler.createObserver(Telemetry.Health.self) 158 | // 159 | // let _ = telemetry.health.subscribe(observer) 160 | // scheduler.start() 161 | // 162 | // var expectedEvents = [Recorded>]() 163 | // for health in healths { 164 | // expectedEvents.append(next(0, Telemetry.Health.translateFromRpc(health))) 165 | // } 166 | // 167 | // XCTAssertEqual(expectedEvents.count, observer.events.count) 168 | // XCTAssertTrue(observer.events.elementsEqual(expectedEvents, by: { (observed, expected) in 169 | // observed.value == expected.value 170 | // })) 171 | // } 172 | // 173 | // func createHealthResponse(health: Mavsdk_Rpc_Telemetry_Health) -> Mavsdk_Rpc_Telemetry_HealthResponse { 174 | // var response = Mavsdk_Rpc_Telemetry_HealthResponse() 175 | // response.health = health 176 | // 177 | // return response 178 | // } 179 | // 180 | // func generateRandomBool() -> Bool { 181 | // return arc4random_uniform(2) == 0 182 | // } 183 | // 184 | // func createRandomRPCHealth() -> Mavsdk_Rpc_Telemetry_Health { 185 | // var health = Mavsdk_Rpc_Telemetry_Health() 186 | // 187 | // health.isGyrometerCalibrationOk = generateRandomBool() 188 | // health.isAccelerometerCalibrationOk = generateRandomBool() 189 | // health.isMagnetometerCalibrationOk = generateRandomBool() 190 | // health.isLevelCalibrationOk = generateRandomBool() 191 | // health.isLocalPositionOk = generateRandomBool() 192 | // health.isGlobalPositionOk = generateRandomBool() 193 | // health.isHomePositionOk = generateRandomBool() 194 | // 195 | // return health 196 | // } 197 | } 198 | -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/shell.grpc.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DO NOT EDIT. 3 | // 4 | // Generated by the protocol buffer compiler. 5 | // Source: shell.proto 6 | // 7 | 8 | // 9 | // Copyright 2018, gRPC Authors All rights reserved. 10 | // 11 | // Licensed under the Apache License, Version 2.0 (the "License"); 12 | // you may not use this file except in compliance with the License. 13 | // You may obtain a copy of the License at 14 | // 15 | // http://www.apache.org/licenses/LICENSE-2.0 16 | // 17 | // Unless required by applicable law or agreed to in writing, software 18 | // distributed under the License is distributed on an "AS IS" BASIS, 19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | // See the License for the specific language governing permissions and 21 | // limitations under the License. 22 | // 23 | import GRPC 24 | import NIO 25 | import SwiftProtobuf 26 | 27 | 28 | ///* 29 | /// Allow to communicate with the vehicle's system shell. 30 | /// 31 | /// Usage: instantiate `Mavsdk_Rpc_Shell_ShellServiceClient`, then call methods of this protocol to make API calls. 32 | internal protocol Mavsdk_Rpc_Shell_ShellServiceClientProtocol: GRPCClient { 33 | var serviceName: String { get } 34 | var interceptors: Mavsdk_Rpc_Shell_ShellServiceClientInterceptorFactoryProtocol? { get } 35 | 36 | func send( 37 | _ request: Mavsdk_Rpc_Shell_SendRequest, 38 | callOptions: CallOptions? 39 | ) -> UnaryCall 40 | 41 | func subscribeReceive( 42 | _ request: Mavsdk_Rpc_Shell_SubscribeReceiveRequest, 43 | callOptions: CallOptions?, 44 | handler: @escaping (Mavsdk_Rpc_Shell_ReceiveResponse) -> Void 45 | ) -> ServerStreamingCall 46 | } 47 | 48 | extension Mavsdk_Rpc_Shell_ShellServiceClientProtocol { 49 | internal var serviceName: String { 50 | return "mavsdk.rpc.shell.ShellService" 51 | } 52 | 53 | /// 54 | /// Send a command line. 55 | /// 56 | /// - Parameters: 57 | /// - request: Request to send to Send. 58 | /// - callOptions: Call options. 59 | /// - Returns: A `UnaryCall` with futures for the metadata, status and response. 60 | internal func send( 61 | _ request: Mavsdk_Rpc_Shell_SendRequest, 62 | callOptions: CallOptions? = nil 63 | ) -> UnaryCall { 64 | return self.makeUnaryCall( 65 | path: "/mavsdk.rpc.shell.ShellService/Send", 66 | request: request, 67 | callOptions: callOptions ?? self.defaultCallOptions, 68 | interceptors: self.interceptors?.makeSendInterceptors() ?? [] 69 | ) 70 | } 71 | 72 | /// 73 | /// Receive feedback from a sent command line. 74 | /// 75 | /// This subscription needs to be made before a command line is sent, otherwise, no response will be sent. 76 | /// 77 | /// - Parameters: 78 | /// - request: Request to send to SubscribeReceive. 79 | /// - callOptions: Call options. 80 | /// - handler: A closure called when each response is received from the server. 81 | /// - Returns: A `ServerStreamingCall` with futures for the metadata and status. 82 | internal func subscribeReceive( 83 | _ request: Mavsdk_Rpc_Shell_SubscribeReceiveRequest, 84 | callOptions: CallOptions? = nil, 85 | handler: @escaping (Mavsdk_Rpc_Shell_ReceiveResponse) -> Void 86 | ) -> ServerStreamingCall { 87 | return self.makeServerStreamingCall( 88 | path: "/mavsdk.rpc.shell.ShellService/SubscribeReceive", 89 | request: request, 90 | callOptions: callOptions ?? self.defaultCallOptions, 91 | interceptors: self.interceptors?.makeSubscribeReceiveInterceptors() ?? [], 92 | handler: handler 93 | ) 94 | } 95 | } 96 | 97 | internal protocol Mavsdk_Rpc_Shell_ShellServiceClientInterceptorFactoryProtocol { 98 | 99 | /// - Returns: Interceptors to use when invoking 'send'. 100 | func makeSendInterceptors() -> [ClientInterceptor] 101 | 102 | /// - Returns: Interceptors to use when invoking 'subscribeReceive'. 103 | func makeSubscribeReceiveInterceptors() -> [ClientInterceptor] 104 | } 105 | 106 | internal final class Mavsdk_Rpc_Shell_ShellServiceClient: Mavsdk_Rpc_Shell_ShellServiceClientProtocol { 107 | internal let channel: GRPCChannel 108 | internal var defaultCallOptions: CallOptions 109 | internal var interceptors: Mavsdk_Rpc_Shell_ShellServiceClientInterceptorFactoryProtocol? 110 | 111 | /// Creates a client for the mavsdk.rpc.shell.ShellService service. 112 | /// 113 | /// - Parameters: 114 | /// - channel: `GRPCChannel` to the service host. 115 | /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. 116 | /// - interceptors: A factory providing interceptors for each RPC. 117 | internal init( 118 | channel: GRPCChannel, 119 | defaultCallOptions: CallOptions = CallOptions(), 120 | interceptors: Mavsdk_Rpc_Shell_ShellServiceClientInterceptorFactoryProtocol? = nil 121 | ) { 122 | self.channel = channel 123 | self.defaultCallOptions = defaultCallOptions 124 | self.interceptors = interceptors 125 | } 126 | } 127 | 128 | ///* 129 | /// Allow to communicate with the vehicle's system shell. 130 | /// 131 | /// To build a server, implement a class that conforms to this protocol. 132 | internal protocol Mavsdk_Rpc_Shell_ShellServiceProvider: CallHandlerProvider { 133 | var interceptors: Mavsdk_Rpc_Shell_ShellServiceServerInterceptorFactoryProtocol? { get } 134 | 135 | /// 136 | /// Send a command line. 137 | func send(request: Mavsdk_Rpc_Shell_SendRequest, context: StatusOnlyCallContext) -> EventLoopFuture 138 | 139 | /// 140 | /// Receive feedback from a sent command line. 141 | /// 142 | /// This subscription needs to be made before a command line is sent, otherwise, no response will be sent. 143 | func subscribeReceive(request: Mavsdk_Rpc_Shell_SubscribeReceiveRequest, context: StreamingResponseCallContext) -> EventLoopFuture 144 | } 145 | 146 | extension Mavsdk_Rpc_Shell_ShellServiceProvider { 147 | internal var serviceName: Substring { return "mavsdk.rpc.shell.ShellService" } 148 | 149 | /// Determines, calls and returns the appropriate request handler, depending on the request's method. 150 | /// Returns nil for methods not handled by this service. 151 | internal func handle( 152 | method name: Substring, 153 | context: CallHandlerContext 154 | ) -> GRPCServerHandlerProtocol? { 155 | switch name { 156 | case "Send": 157 | return UnaryServerHandler( 158 | context: context, 159 | requestDeserializer: ProtobufDeserializer(), 160 | responseSerializer: ProtobufSerializer(), 161 | interceptors: self.interceptors?.makeSendInterceptors() ?? [], 162 | userFunction: self.send(request:context:) 163 | ) 164 | 165 | case "SubscribeReceive": 166 | return ServerStreamingServerHandler( 167 | context: context, 168 | requestDeserializer: ProtobufDeserializer(), 169 | responseSerializer: ProtobufSerializer(), 170 | interceptors: self.interceptors?.makeSubscribeReceiveInterceptors() ?? [], 171 | userFunction: self.subscribeReceive(request:context:) 172 | ) 173 | 174 | default: 175 | return nil 176 | } 177 | } 178 | } 179 | 180 | internal protocol Mavsdk_Rpc_Shell_ShellServiceServerInterceptorFactoryProtocol { 181 | 182 | /// - Returns: Interceptors to use when handling 'send'. 183 | /// Defaults to calling `self.makeInterceptors()`. 184 | func makeSendInterceptors() -> [ServerInterceptor] 185 | 186 | /// - Returns: Interceptors to use when handling 'subscribeReceive'. 187 | /// Defaults to calling `self.makeInterceptors()`. 188 | func makeSubscribeReceiveInterceptors() -> [ServerInterceptor] 189 | } 190 | -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/Shell.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import RxSwift 3 | import GRPC 4 | import NIO 5 | 6 | /** 7 | * 8 | Allow to communicate with the vehicle's system shell. 9 | */ 10 | public class Shell { 11 | private let service: Mavsdk_Rpc_Shell_ShellServiceClient 12 | private let scheduler: SchedulerType 13 | private let clientEventLoopGroup: EventLoopGroup 14 | 15 | /** 16 | Initializes a new `Shell` plugin. 17 | 18 | Normally never created manually, but used from the `Drone` helper class instead. 19 | 20 | - Parameters: 21 | - address: The address of the `MavsdkServer` instance to connect to 22 | - port: The port of the `MavsdkServer` instance to connect to 23 | - scheduler: The scheduler to be used by `Observable`s 24 | */ 25 | public convenience init(address: String = "localhost", 26 | port: Int32 = 50051, 27 | scheduler: SchedulerType = ConcurrentDispatchQueueScheduler(qos: .background)) { 28 | let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 2) 29 | let channel = ClientConnection.insecure(group: eventLoopGroup).connect(host: address, port: Int(port)) 30 | let service = Mavsdk_Rpc_Shell_ShellServiceClient(channel: channel) 31 | 32 | self.init(service: service, scheduler: scheduler, eventLoopGroup: eventLoopGroup) 33 | } 34 | 35 | init(service: Mavsdk_Rpc_Shell_ShellServiceClient, scheduler: SchedulerType, eventLoopGroup: EventLoopGroup) { 36 | self.service = service 37 | self.scheduler = scheduler 38 | self.clientEventLoopGroup = eventLoopGroup 39 | } 40 | 41 | public struct RuntimeShellError: Error { 42 | public let description: String 43 | 44 | init(_ description: String) { 45 | self.description = description 46 | } 47 | } 48 | 49 | 50 | public struct ShellError: Error { 51 | public let code: Shell.ShellResult.Result 52 | public let description: String 53 | } 54 | 55 | 56 | 57 | /** 58 | Result type. 59 | */ 60 | public struct ShellResult: Equatable { 61 | public let result: Result 62 | public let resultStr: String 63 | 64 | 65 | 66 | 67 | /** 68 | Possible results returned for shell requests 69 | */ 70 | public enum Result: Equatable { 71 | /// Unknown result. 72 | case unknown 73 | /// Request succeeded. 74 | case success 75 | /// No system is connected. 76 | case noSystem 77 | /// Connection error. 78 | case connectionError 79 | /// Response was not received. 80 | case noResponse 81 | /// Shell busy (transfer in progress). 82 | case busy 83 | case UNRECOGNIZED(Int) 84 | 85 | internal var rpcResult: Mavsdk_Rpc_Shell_ShellResult.Result { 86 | switch self { 87 | case .unknown: 88 | return .unknown 89 | case .success: 90 | return .success 91 | case .noSystem: 92 | return .noSystem 93 | case .connectionError: 94 | return .connectionError 95 | case .noResponse: 96 | return .noResponse 97 | case .busy: 98 | return .busy 99 | case .UNRECOGNIZED(let i): 100 | return .UNRECOGNIZED(i) 101 | } 102 | } 103 | 104 | internal static func translateFromRpc(_ rpcResult: Mavsdk_Rpc_Shell_ShellResult.Result) -> Result { 105 | switch rpcResult { 106 | case .unknown: 107 | return .unknown 108 | case .success: 109 | return .success 110 | case .noSystem: 111 | return .noSystem 112 | case .connectionError: 113 | return .connectionError 114 | case .noResponse: 115 | return .noResponse 116 | case .busy: 117 | return .busy 118 | case .UNRECOGNIZED(let i): 119 | return .UNRECOGNIZED(i) 120 | } 121 | } 122 | } 123 | 124 | 125 | /** 126 | Initializes a new `ShellResult`. 127 | 128 | 129 | - Parameters: 130 | 131 | - result: Result enum value 132 | 133 | - resultStr: Human-readable English string describing the result 134 | 135 | 136 | */ 137 | public init(result: Result, resultStr: String) { 138 | self.result = result 139 | self.resultStr = resultStr 140 | } 141 | 142 | internal var rpcShellResult: Mavsdk_Rpc_Shell_ShellResult { 143 | var rpcShellResult = Mavsdk_Rpc_Shell_ShellResult() 144 | 145 | 146 | rpcShellResult.result = result.rpcResult 147 | 148 | 149 | 150 | 151 | rpcShellResult.resultStr = resultStr 152 | 153 | 154 | 155 | return rpcShellResult 156 | } 157 | 158 | internal static func translateFromRpc(_ rpcShellResult: Mavsdk_Rpc_Shell_ShellResult) -> ShellResult { 159 | return ShellResult(result: Result.translateFromRpc(rpcShellResult.result), resultStr: rpcShellResult.resultStr) 160 | } 161 | 162 | public static func == (lhs: ShellResult, rhs: ShellResult) -> Bool { 163 | return lhs.result == rhs.result 164 | && lhs.resultStr == rhs.resultStr 165 | } 166 | } 167 | 168 | 169 | /** 170 | Send a command line. 171 | 172 | - Parameter command: The command line to send 173 | 174 | */ 175 | public func send(command: String) -> Completable { 176 | return Completable.create { completable in 177 | var request = Mavsdk_Rpc_Shell_SendRequest() 178 | 179 | 180 | 181 | request.command = command 182 | 183 | 184 | 185 | do { 186 | 187 | let response = self.service.send(request) 188 | 189 | let result = try response.response.wait().shellResult 190 | if (result.result == Mavsdk_Rpc_Shell_ShellResult.Result.success) { 191 | completable(.completed) 192 | } else { 193 | completable(.error(ShellError(code: ShellResult.Result.translateFromRpc(result.result), description: result.resultStr))) 194 | } 195 | 196 | } catch { 197 | completable(.error(error)) 198 | } 199 | 200 | return Disposables.create() 201 | } 202 | } 203 | 204 | 205 | /** 206 | Receive feedback from a sent command line. 207 | 208 | This subscription needs to be made before a command line is sent, otherwise, no response will be sent. 209 | */ 210 | public lazy var receive: Observable = createReceiveObservable() 211 | 212 | 213 | 214 | private func createReceiveObservable() -> Observable { 215 | return Observable.create { [unowned self] observer in 216 | let request = Mavsdk_Rpc_Shell_SubscribeReceiveRequest() 217 | 218 | 219 | 220 | let serverStreamingCall = self.service.subscribeReceive(request, handler: { (response) in 221 | 222 | 223 | 224 | let receive = response.data 225 | 226 | 227 | 228 | 229 | observer.onNext(receive) 230 | 231 | }) 232 | 233 | return Disposables.create { 234 | serverStreamingCall.cancel(promise: nil) 235 | } 236 | } 237 | .retry { error in 238 | error.map { 239 | guard $0 is RuntimeShellError else { throw $0 } 240 | } 241 | } 242 | .share(replay: 1) 243 | } 244 | } -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/geofence.grpc.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DO NOT EDIT. 3 | // 4 | // Generated by the protocol buffer compiler. 5 | // Source: geofence.proto 6 | // 7 | 8 | // 9 | // Copyright 2018, gRPC Authors All rights reserved. 10 | // 11 | // Licensed under the Apache License, Version 2.0 (the "License"); 12 | // you may not use this file except in compliance with the License. 13 | // You may obtain a copy of the License at 14 | // 15 | // http://www.apache.org/licenses/LICENSE-2.0 16 | // 17 | // Unless required by applicable law or agreed to in writing, software 18 | // distributed under the License is distributed on an "AS IS" BASIS, 19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | // See the License for the specific language governing permissions and 21 | // limitations under the License. 22 | // 23 | import GRPC 24 | import NIO 25 | import SwiftProtobuf 26 | 27 | 28 | /// Enable setting a geofence. 29 | /// 30 | /// Usage: instantiate `Mavsdk_Rpc_Geofence_GeofenceServiceClient`, then call methods of this protocol to make API calls. 31 | internal protocol Mavsdk_Rpc_Geofence_GeofenceServiceClientProtocol: GRPCClient { 32 | var serviceName: String { get } 33 | var interceptors: Mavsdk_Rpc_Geofence_GeofenceServiceClientInterceptorFactoryProtocol? { get } 34 | 35 | func uploadGeofence( 36 | _ request: Mavsdk_Rpc_Geofence_UploadGeofenceRequest, 37 | callOptions: CallOptions? 38 | ) -> UnaryCall 39 | 40 | func clearGeofence( 41 | _ request: Mavsdk_Rpc_Geofence_ClearGeofenceRequest, 42 | callOptions: CallOptions? 43 | ) -> UnaryCall 44 | } 45 | 46 | extension Mavsdk_Rpc_Geofence_GeofenceServiceClientProtocol { 47 | internal var serviceName: String { 48 | return "mavsdk.rpc.geofence.GeofenceService" 49 | } 50 | 51 | /// 52 | /// Upload a geofence. 53 | /// 54 | /// Polygons are uploaded to a drone. Once uploaded, the geofence will remain 55 | /// on the drone even if a connection is lost. 56 | /// 57 | /// - Parameters: 58 | /// - request: Request to send to UploadGeofence. 59 | /// - callOptions: Call options. 60 | /// - Returns: A `UnaryCall` with futures for the metadata, status and response. 61 | internal func uploadGeofence( 62 | _ request: Mavsdk_Rpc_Geofence_UploadGeofenceRequest, 63 | callOptions: CallOptions? = nil 64 | ) -> UnaryCall { 65 | return self.makeUnaryCall( 66 | path: "/mavsdk.rpc.geofence.GeofenceService/UploadGeofence", 67 | request: request, 68 | callOptions: callOptions ?? self.defaultCallOptions, 69 | interceptors: self.interceptors?.makeUploadGeofenceInterceptors() ?? [] 70 | ) 71 | } 72 | 73 | /// 74 | /// Clear all geofences saved on the vehicle. 75 | /// 76 | /// - Parameters: 77 | /// - request: Request to send to ClearGeofence. 78 | /// - callOptions: Call options. 79 | /// - Returns: A `UnaryCall` with futures for the metadata, status and response. 80 | internal func clearGeofence( 81 | _ request: Mavsdk_Rpc_Geofence_ClearGeofenceRequest, 82 | callOptions: CallOptions? = nil 83 | ) -> UnaryCall { 84 | return self.makeUnaryCall( 85 | path: "/mavsdk.rpc.geofence.GeofenceService/ClearGeofence", 86 | request: request, 87 | callOptions: callOptions ?? self.defaultCallOptions, 88 | interceptors: self.interceptors?.makeClearGeofenceInterceptors() ?? [] 89 | ) 90 | } 91 | } 92 | 93 | internal protocol Mavsdk_Rpc_Geofence_GeofenceServiceClientInterceptorFactoryProtocol { 94 | 95 | /// - Returns: Interceptors to use when invoking 'uploadGeofence'. 96 | func makeUploadGeofenceInterceptors() -> [ClientInterceptor] 97 | 98 | /// - Returns: Interceptors to use when invoking 'clearGeofence'. 99 | func makeClearGeofenceInterceptors() -> [ClientInterceptor] 100 | } 101 | 102 | internal final class Mavsdk_Rpc_Geofence_GeofenceServiceClient: Mavsdk_Rpc_Geofence_GeofenceServiceClientProtocol { 103 | internal let channel: GRPCChannel 104 | internal var defaultCallOptions: CallOptions 105 | internal var interceptors: Mavsdk_Rpc_Geofence_GeofenceServiceClientInterceptorFactoryProtocol? 106 | 107 | /// Creates a client for the mavsdk.rpc.geofence.GeofenceService service. 108 | /// 109 | /// - Parameters: 110 | /// - channel: `GRPCChannel` to the service host. 111 | /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. 112 | /// - interceptors: A factory providing interceptors for each RPC. 113 | internal init( 114 | channel: GRPCChannel, 115 | defaultCallOptions: CallOptions = CallOptions(), 116 | interceptors: Mavsdk_Rpc_Geofence_GeofenceServiceClientInterceptorFactoryProtocol? = nil 117 | ) { 118 | self.channel = channel 119 | self.defaultCallOptions = defaultCallOptions 120 | self.interceptors = interceptors 121 | } 122 | } 123 | 124 | /// Enable setting a geofence. 125 | /// 126 | /// To build a server, implement a class that conforms to this protocol. 127 | internal protocol Mavsdk_Rpc_Geofence_GeofenceServiceProvider: CallHandlerProvider { 128 | var interceptors: Mavsdk_Rpc_Geofence_GeofenceServiceServerInterceptorFactoryProtocol? { get } 129 | 130 | /// 131 | /// Upload a geofence. 132 | /// 133 | /// Polygons are uploaded to a drone. Once uploaded, the geofence will remain 134 | /// on the drone even if a connection is lost. 135 | func uploadGeofence(request: Mavsdk_Rpc_Geofence_UploadGeofenceRequest, context: StatusOnlyCallContext) -> EventLoopFuture 136 | 137 | /// 138 | /// Clear all geofences saved on the vehicle. 139 | func clearGeofence(request: Mavsdk_Rpc_Geofence_ClearGeofenceRequest, context: StatusOnlyCallContext) -> EventLoopFuture 140 | } 141 | 142 | extension Mavsdk_Rpc_Geofence_GeofenceServiceProvider { 143 | internal var serviceName: Substring { return "mavsdk.rpc.geofence.GeofenceService" } 144 | 145 | /// Determines, calls and returns the appropriate request handler, depending on the request's method. 146 | /// Returns nil for methods not handled by this service. 147 | internal func handle( 148 | method name: Substring, 149 | context: CallHandlerContext 150 | ) -> GRPCServerHandlerProtocol? { 151 | switch name { 152 | case "UploadGeofence": 153 | return UnaryServerHandler( 154 | context: context, 155 | requestDeserializer: ProtobufDeserializer(), 156 | responseSerializer: ProtobufSerializer(), 157 | interceptors: self.interceptors?.makeUploadGeofenceInterceptors() ?? [], 158 | userFunction: self.uploadGeofence(request:context:) 159 | ) 160 | 161 | case "ClearGeofence": 162 | return UnaryServerHandler( 163 | context: context, 164 | requestDeserializer: ProtobufDeserializer(), 165 | responseSerializer: ProtobufSerializer(), 166 | interceptors: self.interceptors?.makeClearGeofenceInterceptors() ?? [], 167 | userFunction: self.clearGeofence(request:context:) 168 | ) 169 | 170 | default: 171 | return nil 172 | } 173 | } 174 | } 175 | 176 | internal protocol Mavsdk_Rpc_Geofence_GeofenceServiceServerInterceptorFactoryProtocol { 177 | 178 | /// - Returns: Interceptors to use when handling 'uploadGeofence'. 179 | /// Defaults to calling `self.makeInterceptors()`. 180 | func makeUploadGeofenceInterceptors() -> [ServerInterceptor] 181 | 182 | /// - Returns: Interceptors to use when handling 'clearGeofence'. 183 | /// Defaults to calling `self.makeInterceptors()`. 184 | func makeClearGeofenceInterceptors() -> [ServerInterceptor] 185 | } 186 | -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/transponder.grpc.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DO NOT EDIT. 3 | // 4 | // Generated by the protocol buffer compiler. 5 | // Source: transponder.proto 6 | // 7 | 8 | // 9 | // Copyright 2018, gRPC Authors All rights reserved. 10 | // 11 | // Licensed under the Apache License, Version 2.0 (the "License"); 12 | // you may not use this file except in compliance with the License. 13 | // You may obtain a copy of the License at 14 | // 15 | // http://www.apache.org/licenses/LICENSE-2.0 16 | // 17 | // Unless required by applicable law or agreed to in writing, software 18 | // distributed under the License is distributed on an "AS IS" BASIS, 19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | // See the License for the specific language governing permissions and 21 | // limitations under the License. 22 | // 23 | import GRPC 24 | import NIO 25 | import SwiftProtobuf 26 | 27 | 28 | /// 29 | /// Allow users to get ADS-B information 30 | /// and set ADS-B update rates. 31 | /// 32 | /// Usage: instantiate `Mavsdk_Rpc_Transponder_TransponderServiceClient`, then call methods of this protocol to make API calls. 33 | internal protocol Mavsdk_Rpc_Transponder_TransponderServiceClientProtocol: GRPCClient { 34 | var serviceName: String { get } 35 | var interceptors: Mavsdk_Rpc_Transponder_TransponderServiceClientInterceptorFactoryProtocol? { get } 36 | 37 | func subscribeTransponder( 38 | _ request: Mavsdk_Rpc_Transponder_SubscribeTransponderRequest, 39 | callOptions: CallOptions?, 40 | handler: @escaping (Mavsdk_Rpc_Transponder_TransponderResponse) -> Void 41 | ) -> ServerStreamingCall 42 | 43 | func setRateTransponder( 44 | _ request: Mavsdk_Rpc_Transponder_SetRateTransponderRequest, 45 | callOptions: CallOptions? 46 | ) -> UnaryCall 47 | } 48 | 49 | extension Mavsdk_Rpc_Transponder_TransponderServiceClientProtocol { 50 | internal var serviceName: String { 51 | return "mavsdk.rpc.transponder.TransponderService" 52 | } 53 | 54 | /// Subscribe to 'transponder' updates. 55 | /// 56 | /// - Parameters: 57 | /// - request: Request to send to SubscribeTransponder. 58 | /// - callOptions: Call options. 59 | /// - handler: A closure called when each response is received from the server. 60 | /// - Returns: A `ServerStreamingCall` with futures for the metadata and status. 61 | internal func subscribeTransponder( 62 | _ request: Mavsdk_Rpc_Transponder_SubscribeTransponderRequest, 63 | callOptions: CallOptions? = nil, 64 | handler: @escaping (Mavsdk_Rpc_Transponder_TransponderResponse) -> Void 65 | ) -> ServerStreamingCall { 66 | return self.makeServerStreamingCall( 67 | path: "/mavsdk.rpc.transponder.TransponderService/SubscribeTransponder", 68 | request: request, 69 | callOptions: callOptions ?? self.defaultCallOptions, 70 | interceptors: self.interceptors?.makeSubscribeTransponderInterceptors() ?? [], 71 | handler: handler 72 | ) 73 | } 74 | 75 | /// Set rate to 'transponder' updates. 76 | /// 77 | /// - Parameters: 78 | /// - request: Request to send to SetRateTransponder. 79 | /// - callOptions: Call options. 80 | /// - Returns: A `UnaryCall` with futures for the metadata, status and response. 81 | internal func setRateTransponder( 82 | _ request: Mavsdk_Rpc_Transponder_SetRateTransponderRequest, 83 | callOptions: CallOptions? = nil 84 | ) -> UnaryCall { 85 | return self.makeUnaryCall( 86 | path: "/mavsdk.rpc.transponder.TransponderService/SetRateTransponder", 87 | request: request, 88 | callOptions: callOptions ?? self.defaultCallOptions, 89 | interceptors: self.interceptors?.makeSetRateTransponderInterceptors() ?? [] 90 | ) 91 | } 92 | } 93 | 94 | internal protocol Mavsdk_Rpc_Transponder_TransponderServiceClientInterceptorFactoryProtocol { 95 | 96 | /// - Returns: Interceptors to use when invoking 'subscribeTransponder'. 97 | func makeSubscribeTransponderInterceptors() -> [ClientInterceptor] 98 | 99 | /// - Returns: Interceptors to use when invoking 'setRateTransponder'. 100 | func makeSetRateTransponderInterceptors() -> [ClientInterceptor] 101 | } 102 | 103 | internal final class Mavsdk_Rpc_Transponder_TransponderServiceClient: Mavsdk_Rpc_Transponder_TransponderServiceClientProtocol { 104 | internal let channel: GRPCChannel 105 | internal var defaultCallOptions: CallOptions 106 | internal var interceptors: Mavsdk_Rpc_Transponder_TransponderServiceClientInterceptorFactoryProtocol? 107 | 108 | /// Creates a client for the mavsdk.rpc.transponder.TransponderService service. 109 | /// 110 | /// - Parameters: 111 | /// - channel: `GRPCChannel` to the service host. 112 | /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. 113 | /// - interceptors: A factory providing interceptors for each RPC. 114 | internal init( 115 | channel: GRPCChannel, 116 | defaultCallOptions: CallOptions = CallOptions(), 117 | interceptors: Mavsdk_Rpc_Transponder_TransponderServiceClientInterceptorFactoryProtocol? = nil 118 | ) { 119 | self.channel = channel 120 | self.defaultCallOptions = defaultCallOptions 121 | self.interceptors = interceptors 122 | } 123 | } 124 | 125 | /// 126 | /// Allow users to get ADS-B information 127 | /// and set ADS-B update rates. 128 | /// 129 | /// To build a server, implement a class that conforms to this protocol. 130 | internal protocol Mavsdk_Rpc_Transponder_TransponderServiceProvider: CallHandlerProvider { 131 | var interceptors: Mavsdk_Rpc_Transponder_TransponderServiceServerInterceptorFactoryProtocol? { get } 132 | 133 | /// Subscribe to 'transponder' updates. 134 | func subscribeTransponder(request: Mavsdk_Rpc_Transponder_SubscribeTransponderRequest, context: StreamingResponseCallContext) -> EventLoopFuture 135 | 136 | /// Set rate to 'transponder' updates. 137 | func setRateTransponder(request: Mavsdk_Rpc_Transponder_SetRateTransponderRequest, context: StatusOnlyCallContext) -> EventLoopFuture 138 | } 139 | 140 | extension Mavsdk_Rpc_Transponder_TransponderServiceProvider { 141 | internal var serviceName: Substring { return "mavsdk.rpc.transponder.TransponderService" } 142 | 143 | /// Determines, calls and returns the appropriate request handler, depending on the request's method. 144 | /// Returns nil for methods not handled by this service. 145 | internal func handle( 146 | method name: Substring, 147 | context: CallHandlerContext 148 | ) -> GRPCServerHandlerProtocol? { 149 | switch name { 150 | case "SubscribeTransponder": 151 | return ServerStreamingServerHandler( 152 | context: context, 153 | requestDeserializer: ProtobufDeserializer(), 154 | responseSerializer: ProtobufSerializer(), 155 | interceptors: self.interceptors?.makeSubscribeTransponderInterceptors() ?? [], 156 | userFunction: self.subscribeTransponder(request:context:) 157 | ) 158 | 159 | case "SetRateTransponder": 160 | return UnaryServerHandler( 161 | context: context, 162 | requestDeserializer: ProtobufDeserializer(), 163 | responseSerializer: ProtobufSerializer(), 164 | interceptors: self.interceptors?.makeSetRateTransponderInterceptors() ?? [], 165 | userFunction: self.setRateTransponder(request:context:) 166 | ) 167 | 168 | default: 169 | return nil 170 | } 171 | } 172 | } 173 | 174 | internal protocol Mavsdk_Rpc_Transponder_TransponderServiceServerInterceptorFactoryProtocol { 175 | 176 | /// - Returns: Interceptors to use when handling 'subscribeTransponder'. 177 | /// Defaults to calling `self.makeInterceptors()`. 178 | func makeSubscribeTransponderInterceptors() -> [ServerInterceptor] 179 | 180 | /// - Returns: Interceptors to use when handling 'setRateTransponder'. 181 | /// Defaults to calling `self.makeInterceptors()`. 182 | func makeSetRateTransponderInterceptors() -> [ServerInterceptor] 183 | } 184 | -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/core.grpc.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DO NOT EDIT. 3 | // 4 | // Generated by the protocol buffer compiler. 5 | // Source: core.proto 6 | // 7 | 8 | // 9 | // Copyright 2018, gRPC Authors All rights reserved. 10 | // 11 | // Licensed under the Apache License, Version 2.0 (the "License"); 12 | // you may not use this file except in compliance with the License. 13 | // You may obtain a copy of the License at 14 | // 15 | // http://www.apache.org/licenses/LICENSE-2.0 16 | // 17 | // Unless required by applicable law or agreed to in writing, software 18 | // distributed under the License is distributed on an "AS IS" BASIS, 19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | // See the License for the specific language governing permissions and 21 | // limitations under the License. 22 | // 23 | import GRPC 24 | import NIO 25 | import SwiftProtobuf 26 | 27 | 28 | /// Access to the connection state and core configurations 29 | /// 30 | /// Usage: instantiate `Mavsdk_Rpc_Core_CoreServiceClient`, then call methods of this protocol to make API calls. 31 | internal protocol Mavsdk_Rpc_Core_CoreServiceClientProtocol: GRPCClient { 32 | var serviceName: String { get } 33 | var interceptors: Mavsdk_Rpc_Core_CoreServiceClientInterceptorFactoryProtocol? { get } 34 | 35 | func subscribeConnectionState( 36 | _ request: Mavsdk_Rpc_Core_SubscribeConnectionStateRequest, 37 | callOptions: CallOptions?, 38 | handler: @escaping (Mavsdk_Rpc_Core_ConnectionStateResponse) -> Void 39 | ) -> ServerStreamingCall 40 | 41 | func setMavlinkTimeout( 42 | _ request: Mavsdk_Rpc_Core_SetMavlinkTimeoutRequest, 43 | callOptions: CallOptions? 44 | ) -> UnaryCall 45 | } 46 | 47 | extension Mavsdk_Rpc_Core_CoreServiceClientProtocol { 48 | internal var serviceName: String { 49 | return "mavsdk.rpc.core.CoreService" 50 | } 51 | 52 | /// 53 | /// Subscribe to 'connection state' updates. 54 | /// 55 | /// - Parameters: 56 | /// - request: Request to send to SubscribeConnectionState. 57 | /// - callOptions: Call options. 58 | /// - handler: A closure called when each response is received from the server. 59 | /// - Returns: A `ServerStreamingCall` with futures for the metadata and status. 60 | internal func subscribeConnectionState( 61 | _ request: Mavsdk_Rpc_Core_SubscribeConnectionStateRequest, 62 | callOptions: CallOptions? = nil, 63 | handler: @escaping (Mavsdk_Rpc_Core_ConnectionStateResponse) -> Void 64 | ) -> ServerStreamingCall { 65 | return self.makeServerStreamingCall( 66 | path: "/mavsdk.rpc.core.CoreService/SubscribeConnectionState", 67 | request: request, 68 | callOptions: callOptions ?? self.defaultCallOptions, 69 | interceptors: self.interceptors?.makeSubscribeConnectionStateInterceptors() ?? [], 70 | handler: handler 71 | ) 72 | } 73 | 74 | /// 75 | /// Set timeout of MAVLink transfers. 76 | /// 77 | /// The default timeout used is generally (0.5 seconds) seconds. 78 | /// If MAVSDK is used on the same host this timeout can be reduced, while 79 | /// if MAVSDK has to communicate over links with high latency it might 80 | /// need to be increased to prevent timeouts. 81 | /// 82 | /// - Parameters: 83 | /// - request: Request to send to SetMavlinkTimeout. 84 | /// - callOptions: Call options. 85 | /// - Returns: A `UnaryCall` with futures for the metadata, status and response. 86 | internal func setMavlinkTimeout( 87 | _ request: Mavsdk_Rpc_Core_SetMavlinkTimeoutRequest, 88 | callOptions: CallOptions? = nil 89 | ) -> UnaryCall { 90 | return self.makeUnaryCall( 91 | path: "/mavsdk.rpc.core.CoreService/SetMavlinkTimeout", 92 | request: request, 93 | callOptions: callOptions ?? self.defaultCallOptions, 94 | interceptors: self.interceptors?.makeSetMavlinkTimeoutInterceptors() ?? [] 95 | ) 96 | } 97 | } 98 | 99 | internal protocol Mavsdk_Rpc_Core_CoreServiceClientInterceptorFactoryProtocol { 100 | 101 | /// - Returns: Interceptors to use when invoking 'subscribeConnectionState'. 102 | func makeSubscribeConnectionStateInterceptors() -> [ClientInterceptor] 103 | 104 | /// - Returns: Interceptors to use when invoking 'setMavlinkTimeout'. 105 | func makeSetMavlinkTimeoutInterceptors() -> [ClientInterceptor] 106 | } 107 | 108 | internal final class Mavsdk_Rpc_Core_CoreServiceClient: Mavsdk_Rpc_Core_CoreServiceClientProtocol { 109 | internal let channel: GRPCChannel 110 | internal var defaultCallOptions: CallOptions 111 | internal var interceptors: Mavsdk_Rpc_Core_CoreServiceClientInterceptorFactoryProtocol? 112 | 113 | /// Creates a client for the mavsdk.rpc.core.CoreService service. 114 | /// 115 | /// - Parameters: 116 | /// - channel: `GRPCChannel` to the service host. 117 | /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. 118 | /// - interceptors: A factory providing interceptors for each RPC. 119 | internal init( 120 | channel: GRPCChannel, 121 | defaultCallOptions: CallOptions = CallOptions(), 122 | interceptors: Mavsdk_Rpc_Core_CoreServiceClientInterceptorFactoryProtocol? = nil 123 | ) { 124 | self.channel = channel 125 | self.defaultCallOptions = defaultCallOptions 126 | self.interceptors = interceptors 127 | } 128 | } 129 | 130 | /// Access to the connection state and core configurations 131 | /// 132 | /// To build a server, implement a class that conforms to this protocol. 133 | internal protocol Mavsdk_Rpc_Core_CoreServiceProvider: CallHandlerProvider { 134 | var interceptors: Mavsdk_Rpc_Core_CoreServiceServerInterceptorFactoryProtocol? { get } 135 | 136 | /// 137 | /// Subscribe to 'connection state' updates. 138 | func subscribeConnectionState(request: Mavsdk_Rpc_Core_SubscribeConnectionStateRequest, context: StreamingResponseCallContext) -> EventLoopFuture 139 | 140 | /// 141 | /// Set timeout of MAVLink transfers. 142 | /// 143 | /// The default timeout used is generally (0.5 seconds) seconds. 144 | /// If MAVSDK is used on the same host this timeout can be reduced, while 145 | /// if MAVSDK has to communicate over links with high latency it might 146 | /// need to be increased to prevent timeouts. 147 | func setMavlinkTimeout(request: Mavsdk_Rpc_Core_SetMavlinkTimeoutRequest, context: StatusOnlyCallContext) -> EventLoopFuture 148 | } 149 | 150 | extension Mavsdk_Rpc_Core_CoreServiceProvider { 151 | internal var serviceName: Substring { return "mavsdk.rpc.core.CoreService" } 152 | 153 | /// Determines, calls and returns the appropriate request handler, depending on the request's method. 154 | /// Returns nil for methods not handled by this service. 155 | internal func handle( 156 | method name: Substring, 157 | context: CallHandlerContext 158 | ) -> GRPCServerHandlerProtocol? { 159 | switch name { 160 | case "SubscribeConnectionState": 161 | return ServerStreamingServerHandler( 162 | context: context, 163 | requestDeserializer: ProtobufDeserializer(), 164 | responseSerializer: ProtobufSerializer(), 165 | interceptors: self.interceptors?.makeSubscribeConnectionStateInterceptors() ?? [], 166 | userFunction: self.subscribeConnectionState(request:context:) 167 | ) 168 | 169 | case "SetMavlinkTimeout": 170 | return UnaryServerHandler( 171 | context: context, 172 | requestDeserializer: ProtobufDeserializer(), 173 | responseSerializer: ProtobufSerializer(), 174 | interceptors: self.interceptors?.makeSetMavlinkTimeoutInterceptors() ?? [], 175 | userFunction: self.setMavlinkTimeout(request:context:) 176 | ) 177 | 178 | default: 179 | return nil 180 | } 181 | } 182 | } 183 | 184 | internal protocol Mavsdk_Rpc_Core_CoreServiceServerInterceptorFactoryProtocol { 185 | 186 | /// - Returns: Interceptors to use when handling 'subscribeConnectionState'. 187 | /// Defaults to calling `self.makeInterceptors()`. 188 | func makeSubscribeConnectionStateInterceptors() -> [ServerInterceptor] 189 | 190 | /// - Returns: Interceptors to use when handling 'setMavlinkTimeout'. 191 | /// Defaults to calling `self.makeInterceptors()`. 192 | func makeSetMavlinkTimeoutInterceptors() -> [ServerInterceptor] 193 | } 194 | -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/component_information.grpc.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DO NOT EDIT. 3 | // 4 | // Generated by the protocol buffer compiler. 5 | // Source: component_information.proto 6 | // 7 | 8 | // 9 | // Copyright 2018, gRPC Authors All rights reserved. 10 | // 11 | // Licensed under the Apache License, Version 2.0 (the "License"); 12 | // you may not use this file except in compliance with the License. 13 | // You may obtain a copy of the License at 14 | // 15 | // http://www.apache.org/licenses/LICENSE-2.0 16 | // 17 | // Unless required by applicable law or agreed to in writing, software 18 | // distributed under the License is distributed on an "AS IS" BASIS, 19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | // See the License for the specific language governing permissions and 21 | // limitations under the License. 22 | // 23 | import GRPC 24 | import NIO 25 | import SwiftProtobuf 26 | 27 | 28 | /// Access component information such as parameters. 29 | /// 30 | /// Usage: instantiate `Mavsdk_Rpc_ComponentInformation_ComponentInformationServiceClient`, then call methods of this protocol to make API calls. 31 | internal protocol Mavsdk_Rpc_ComponentInformation_ComponentInformationServiceClientProtocol: GRPCClient { 32 | var serviceName: String { get } 33 | var interceptors: Mavsdk_Rpc_ComponentInformation_ComponentInformationServiceClientInterceptorFactoryProtocol? { get } 34 | 35 | func accessFloatParams( 36 | _ request: Mavsdk_Rpc_ComponentInformation_AccessFloatParamsRequest, 37 | callOptions: CallOptions? 38 | ) -> UnaryCall 39 | 40 | func subscribeFloatParam( 41 | _ request: Mavsdk_Rpc_ComponentInformation_SubscribeFloatParamRequest, 42 | callOptions: CallOptions?, 43 | handler: @escaping (Mavsdk_Rpc_ComponentInformation_FloatParamResponse) -> Void 44 | ) -> ServerStreamingCall 45 | } 46 | 47 | extension Mavsdk_Rpc_ComponentInformation_ComponentInformationServiceClientProtocol { 48 | internal var serviceName: String { 49 | return "mavsdk.rpc.component_information.ComponentInformationService" 50 | } 51 | 52 | /// 53 | /// List available float params. 54 | /// 55 | /// - Parameters: 56 | /// - request: Request to send to AccessFloatParams. 57 | /// - callOptions: Call options. 58 | /// - Returns: A `UnaryCall` with futures for the metadata, status and response. 59 | internal func accessFloatParams( 60 | _ request: Mavsdk_Rpc_ComponentInformation_AccessFloatParamsRequest, 61 | callOptions: CallOptions? = nil 62 | ) -> UnaryCall { 63 | return self.makeUnaryCall( 64 | path: "/mavsdk.rpc.component_information.ComponentInformationService/AccessFloatParams", 65 | request: request, 66 | callOptions: callOptions ?? self.defaultCallOptions, 67 | interceptors: self.interceptors?.makeAccessFloatParamsInterceptors() ?? [] 68 | ) 69 | } 70 | 71 | /// 72 | /// Subscribe to float param changes/updates. 73 | /// 74 | /// - Parameters: 75 | /// - request: Request to send to SubscribeFloatParam. 76 | /// - callOptions: Call options. 77 | /// - handler: A closure called when each response is received from the server. 78 | /// - Returns: A `ServerStreamingCall` with futures for the metadata and status. 79 | internal func subscribeFloatParam( 80 | _ request: Mavsdk_Rpc_ComponentInformation_SubscribeFloatParamRequest, 81 | callOptions: CallOptions? = nil, 82 | handler: @escaping (Mavsdk_Rpc_ComponentInformation_FloatParamResponse) -> Void 83 | ) -> ServerStreamingCall { 84 | return self.makeServerStreamingCall( 85 | path: "/mavsdk.rpc.component_information.ComponentInformationService/SubscribeFloatParam", 86 | request: request, 87 | callOptions: callOptions ?? self.defaultCallOptions, 88 | interceptors: self.interceptors?.makeSubscribeFloatParamInterceptors() ?? [], 89 | handler: handler 90 | ) 91 | } 92 | } 93 | 94 | internal protocol Mavsdk_Rpc_ComponentInformation_ComponentInformationServiceClientInterceptorFactoryProtocol { 95 | 96 | /// - Returns: Interceptors to use when invoking 'accessFloatParams'. 97 | func makeAccessFloatParamsInterceptors() -> [ClientInterceptor] 98 | 99 | /// - Returns: Interceptors to use when invoking 'subscribeFloatParam'. 100 | func makeSubscribeFloatParamInterceptors() -> [ClientInterceptor] 101 | } 102 | 103 | internal final class Mavsdk_Rpc_ComponentInformation_ComponentInformationServiceClient: Mavsdk_Rpc_ComponentInformation_ComponentInformationServiceClientProtocol { 104 | internal let channel: GRPCChannel 105 | internal var defaultCallOptions: CallOptions 106 | internal var interceptors: Mavsdk_Rpc_ComponentInformation_ComponentInformationServiceClientInterceptorFactoryProtocol? 107 | 108 | /// Creates a client for the mavsdk.rpc.component_information.ComponentInformationService service. 109 | /// 110 | /// - Parameters: 111 | /// - channel: `GRPCChannel` to the service host. 112 | /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. 113 | /// - interceptors: A factory providing interceptors for each RPC. 114 | internal init( 115 | channel: GRPCChannel, 116 | defaultCallOptions: CallOptions = CallOptions(), 117 | interceptors: Mavsdk_Rpc_ComponentInformation_ComponentInformationServiceClientInterceptorFactoryProtocol? = nil 118 | ) { 119 | self.channel = channel 120 | self.defaultCallOptions = defaultCallOptions 121 | self.interceptors = interceptors 122 | } 123 | } 124 | 125 | /// Access component information such as parameters. 126 | /// 127 | /// To build a server, implement a class that conforms to this protocol. 128 | internal protocol Mavsdk_Rpc_ComponentInformation_ComponentInformationServiceProvider: CallHandlerProvider { 129 | var interceptors: Mavsdk_Rpc_ComponentInformation_ComponentInformationServiceServerInterceptorFactoryProtocol? { get } 130 | 131 | /// 132 | /// List available float params. 133 | func accessFloatParams(request: Mavsdk_Rpc_ComponentInformation_AccessFloatParamsRequest, context: StatusOnlyCallContext) -> EventLoopFuture 134 | 135 | /// 136 | /// Subscribe to float param changes/updates. 137 | func subscribeFloatParam(request: Mavsdk_Rpc_ComponentInformation_SubscribeFloatParamRequest, context: StreamingResponseCallContext) -> EventLoopFuture 138 | } 139 | 140 | extension Mavsdk_Rpc_ComponentInformation_ComponentInformationServiceProvider { 141 | internal var serviceName: Substring { return "mavsdk.rpc.component_information.ComponentInformationService" } 142 | 143 | /// Determines, calls and returns the appropriate request handler, depending on the request's method. 144 | /// Returns nil for methods not handled by this service. 145 | internal func handle( 146 | method name: Substring, 147 | context: CallHandlerContext 148 | ) -> GRPCServerHandlerProtocol? { 149 | switch name { 150 | case "AccessFloatParams": 151 | return UnaryServerHandler( 152 | context: context, 153 | requestDeserializer: ProtobufDeserializer(), 154 | responseSerializer: ProtobufSerializer(), 155 | interceptors: self.interceptors?.makeAccessFloatParamsInterceptors() ?? [], 156 | userFunction: self.accessFloatParams(request:context:) 157 | ) 158 | 159 | case "SubscribeFloatParam": 160 | return ServerStreamingServerHandler( 161 | context: context, 162 | requestDeserializer: ProtobufDeserializer(), 163 | responseSerializer: ProtobufSerializer(), 164 | interceptors: self.interceptors?.makeSubscribeFloatParamInterceptors() ?? [], 165 | userFunction: self.subscribeFloatParam(request:context:) 166 | ) 167 | 168 | default: 169 | return nil 170 | } 171 | } 172 | } 173 | 174 | internal protocol Mavsdk_Rpc_ComponentInformation_ComponentInformationServiceServerInterceptorFactoryProtocol { 175 | 176 | /// - Returns: Interceptors to use when handling 'accessFloatParams'. 177 | /// Defaults to calling `self.makeInterceptors()`. 178 | func makeAccessFloatParamsInterceptors() -> [ServerInterceptor] 179 | 180 | /// - Returns: Interceptors to use when handling 'subscribeFloatParam'. 181 | /// Defaults to calling `self.makeInterceptors()`. 182 | func makeSubscribeFloatParamInterceptors() -> [ServerInterceptor] 183 | } 184 | -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/ServerUtility.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import RxSwift 3 | import GRPC 4 | import NIO 5 | 6 | /** 7 | Utility for onboard MAVSDK instances for common "server" tasks. 8 | */ 9 | public class ServerUtility { 10 | private let service: Mavsdk_Rpc_ServerUtility_ServerUtilityServiceClient 11 | private let scheduler: SchedulerType 12 | private let clientEventLoopGroup: EventLoopGroup 13 | 14 | /** 15 | Initializes a new `ServerUtility` plugin. 16 | 17 | Normally never created manually, but used from the `Drone` helper class instead. 18 | 19 | - Parameters: 20 | - address: The address of the `MavsdkServer` instance to connect to 21 | - port: The port of the `MavsdkServer` instance to connect to 22 | - scheduler: The scheduler to be used by `Observable`s 23 | */ 24 | public convenience init(address: String = "localhost", 25 | port: Int32 = 50051, 26 | scheduler: SchedulerType = ConcurrentDispatchQueueScheduler(qos: .background)) { 27 | let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 2) 28 | let channel = ClientConnection.insecure(group: eventLoopGroup).connect(host: address, port: Int(port)) 29 | let service = Mavsdk_Rpc_ServerUtility_ServerUtilityServiceClient(channel: channel) 30 | 31 | self.init(service: service, scheduler: scheduler, eventLoopGroup: eventLoopGroup) 32 | } 33 | 34 | init(service: Mavsdk_Rpc_ServerUtility_ServerUtilityServiceClient, scheduler: SchedulerType, eventLoopGroup: EventLoopGroup) { 35 | self.service = service 36 | self.scheduler = scheduler 37 | self.clientEventLoopGroup = eventLoopGroup 38 | } 39 | 40 | public struct RuntimeServerUtilityError: Error { 41 | public let description: String 42 | 43 | init(_ description: String) { 44 | self.description = description 45 | } 46 | } 47 | 48 | 49 | public struct ServerUtilityError: Error { 50 | public let code: ServerUtility.ServerUtilityResult.Result 51 | public let description: String 52 | } 53 | 54 | 55 | /** 56 | Status types. 57 | */ 58 | public enum StatusTextType: Equatable { 59 | /// Debug. 60 | case debug 61 | /// Information. 62 | case info 63 | /// Notice. 64 | case notice 65 | /// Warning. 66 | case warning 67 | /// Error. 68 | case error 69 | /// Critical. 70 | case critical 71 | /// Alert. 72 | case alert 73 | /// Emergency. 74 | case emergency 75 | case UNRECOGNIZED(Int) 76 | 77 | internal var rpcStatusTextType: Mavsdk_Rpc_ServerUtility_StatusTextType { 78 | switch self { 79 | case .debug: 80 | return .debug 81 | case .info: 82 | return .info 83 | case .notice: 84 | return .notice 85 | case .warning: 86 | return .warning 87 | case .error: 88 | return .error 89 | case .critical: 90 | return .critical 91 | case .alert: 92 | return .alert 93 | case .emergency: 94 | return .emergency 95 | case .UNRECOGNIZED(let i): 96 | return .UNRECOGNIZED(i) 97 | } 98 | } 99 | 100 | internal static func translateFromRpc(_ rpcStatusTextType: Mavsdk_Rpc_ServerUtility_StatusTextType) -> StatusTextType { 101 | switch rpcStatusTextType { 102 | case .debug: 103 | return .debug 104 | case .info: 105 | return .info 106 | case .notice: 107 | return .notice 108 | case .warning: 109 | return .warning 110 | case .error: 111 | return .error 112 | case .critical: 113 | return .critical 114 | case .alert: 115 | return .alert 116 | case .emergency: 117 | return .emergency 118 | case .UNRECOGNIZED(let i): 119 | return .UNRECOGNIZED(i) 120 | } 121 | } 122 | } 123 | 124 | 125 | /** 126 | 127 | */ 128 | public struct ServerUtilityResult: Equatable { 129 | public let result: Result 130 | public let resultStr: String 131 | 132 | 133 | 134 | 135 | /** 136 | Possible results returned for server utility requests. 137 | */ 138 | public enum Result: Equatable { 139 | /// Unknown result. 140 | case unknown 141 | /// Request succeeded. 142 | case success 143 | /// No system is connected. 144 | case noSystem 145 | /// Connection error. 146 | case connectionError 147 | /// Invalid argument. 148 | case invalidArgument 149 | case UNRECOGNIZED(Int) 150 | 151 | internal var rpcResult: Mavsdk_Rpc_ServerUtility_ServerUtilityResult.Result { 152 | switch self { 153 | case .unknown: 154 | return .unknown 155 | case .success: 156 | return .success 157 | case .noSystem: 158 | return .noSystem 159 | case .connectionError: 160 | return .connectionError 161 | case .invalidArgument: 162 | return .invalidArgument 163 | case .UNRECOGNIZED(let i): 164 | return .UNRECOGNIZED(i) 165 | } 166 | } 167 | 168 | internal static func translateFromRpc(_ rpcResult: Mavsdk_Rpc_ServerUtility_ServerUtilityResult.Result) -> Result { 169 | switch rpcResult { 170 | case .unknown: 171 | return .unknown 172 | case .success: 173 | return .success 174 | case .noSystem: 175 | return .noSystem 176 | case .connectionError: 177 | return .connectionError 178 | case .invalidArgument: 179 | return .invalidArgument 180 | case .UNRECOGNIZED(let i): 181 | return .UNRECOGNIZED(i) 182 | } 183 | } 184 | } 185 | 186 | 187 | /** 188 | Initializes a new `ServerUtilityResult`. 189 | 190 | 191 | - Parameters: 192 | 193 | - result: Result enum value 194 | 195 | - resultStr: Human-readable English string describing the result 196 | 197 | 198 | */ 199 | public init(result: Result, resultStr: String) { 200 | self.result = result 201 | self.resultStr = resultStr 202 | } 203 | 204 | internal var rpcServerUtilityResult: Mavsdk_Rpc_ServerUtility_ServerUtilityResult { 205 | var rpcServerUtilityResult = Mavsdk_Rpc_ServerUtility_ServerUtilityResult() 206 | 207 | 208 | rpcServerUtilityResult.result = result.rpcResult 209 | 210 | 211 | 212 | 213 | rpcServerUtilityResult.resultStr = resultStr 214 | 215 | 216 | 217 | return rpcServerUtilityResult 218 | } 219 | 220 | internal static func translateFromRpc(_ rpcServerUtilityResult: Mavsdk_Rpc_ServerUtility_ServerUtilityResult) -> ServerUtilityResult { 221 | return ServerUtilityResult(result: Result.translateFromRpc(rpcServerUtilityResult.result), resultStr: rpcServerUtilityResult.resultStr) 222 | } 223 | 224 | public static func == (lhs: ServerUtilityResult, rhs: ServerUtilityResult) -> Bool { 225 | return lhs.result == rhs.result 226 | && lhs.resultStr == rhs.resultStr 227 | } 228 | } 229 | 230 | 231 | /** 232 | Sends a statustext. 233 | 234 | - Parameters: 235 | - type: The text to send 236 | - text: Text message 237 | 238 | */ 239 | public func sendStatusText(type: StatusTextType, text: String) -> Completable { 240 | return Completable.create { completable in 241 | var request = Mavsdk_Rpc_ServerUtility_SendStatusTextRequest() 242 | 243 | 244 | 245 | request.type = type.rpcStatusTextType 246 | 247 | 248 | 249 | request.text = text 250 | 251 | 252 | 253 | do { 254 | 255 | let response = self.service.sendStatusText(request) 256 | 257 | let result = try response.response.wait().serverUtilityResult 258 | if (result.result == Mavsdk_Rpc_ServerUtility_ServerUtilityResult.Result.success) { 259 | completable(.completed) 260 | } else { 261 | completable(.error(ServerUtilityError(code: ServerUtilityResult.Result.translateFromRpc(result.result), description: result.resultStr))) 262 | } 263 | 264 | } catch { 265 | completable(.error(error)) 266 | } 267 | 268 | return Disposables.create() 269 | } 270 | } 271 | } -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/component_information_server.grpc.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DO NOT EDIT. 3 | // 4 | // Generated by the protocol buffer compiler. 5 | // Source: component_information_server.proto 6 | // 7 | 8 | // 9 | // Copyright 2018, gRPC Authors All rights reserved. 10 | // 11 | // Licensed under the Apache License, Version 2.0 (the "License"); 12 | // you may not use this file except in compliance with the License. 13 | // You may obtain a copy of the License at 14 | // 15 | // http://www.apache.org/licenses/LICENSE-2.0 16 | // 17 | // Unless required by applicable law or agreed to in writing, software 18 | // distributed under the License is distributed on an "AS IS" BASIS, 19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | // See the License for the specific language governing permissions and 21 | // limitations under the License. 22 | // 23 | import GRPC 24 | import NIO 25 | import SwiftProtobuf 26 | 27 | 28 | /// Provide component information such as parameters. 29 | /// 30 | /// Usage: instantiate `Mavsdk_Rpc_ComponentInformationServer_ComponentInformationServerServiceClient`, then call methods of this protocol to make API calls. 31 | internal protocol Mavsdk_Rpc_ComponentInformationServer_ComponentInformationServerServiceClientProtocol: GRPCClient { 32 | var serviceName: String { get } 33 | var interceptors: Mavsdk_Rpc_ComponentInformationServer_ComponentInformationServerServiceClientInterceptorFactoryProtocol? { get } 34 | 35 | func provideFloatParam( 36 | _ request: Mavsdk_Rpc_ComponentInformationServer_ProvideFloatParamRequest, 37 | callOptions: CallOptions? 38 | ) -> UnaryCall 39 | 40 | func subscribeFloatParam( 41 | _ request: Mavsdk_Rpc_ComponentInformationServer_SubscribeFloatParamRequest, 42 | callOptions: CallOptions?, 43 | handler: @escaping (Mavsdk_Rpc_ComponentInformationServer_FloatParamResponse) -> Void 44 | ) -> ServerStreamingCall 45 | } 46 | 47 | extension Mavsdk_Rpc_ComponentInformationServer_ComponentInformationServerServiceClientProtocol { 48 | internal var serviceName: String { 49 | return "mavsdk.rpc.component_information_server.ComponentInformationServerService" 50 | } 51 | 52 | /// 53 | /// Provide a param of type float. 54 | /// 55 | /// - Parameters: 56 | /// - request: Request to send to ProvideFloatParam. 57 | /// - callOptions: Call options. 58 | /// - Returns: A `UnaryCall` with futures for the metadata, status and response. 59 | internal func provideFloatParam( 60 | _ request: Mavsdk_Rpc_ComponentInformationServer_ProvideFloatParamRequest, 61 | callOptions: CallOptions? = nil 62 | ) -> UnaryCall { 63 | return self.makeUnaryCall( 64 | path: "/mavsdk.rpc.component_information_server.ComponentInformationServerService/ProvideFloatParam", 65 | request: request, 66 | callOptions: callOptions ?? self.defaultCallOptions, 67 | interceptors: self.interceptors?.makeProvideFloatParamInterceptors() ?? [] 68 | ) 69 | } 70 | 71 | /// 72 | /// Subscribe to float param updates. 73 | /// 74 | /// - Parameters: 75 | /// - request: Request to send to SubscribeFloatParam. 76 | /// - callOptions: Call options. 77 | /// - handler: A closure called when each response is received from the server. 78 | /// - Returns: A `ServerStreamingCall` with futures for the metadata and status. 79 | internal func subscribeFloatParam( 80 | _ request: Mavsdk_Rpc_ComponentInformationServer_SubscribeFloatParamRequest, 81 | callOptions: CallOptions? = nil, 82 | handler: @escaping (Mavsdk_Rpc_ComponentInformationServer_FloatParamResponse) -> Void 83 | ) -> ServerStreamingCall { 84 | return self.makeServerStreamingCall( 85 | path: "/mavsdk.rpc.component_information_server.ComponentInformationServerService/SubscribeFloatParam", 86 | request: request, 87 | callOptions: callOptions ?? self.defaultCallOptions, 88 | interceptors: self.interceptors?.makeSubscribeFloatParamInterceptors() ?? [], 89 | handler: handler 90 | ) 91 | } 92 | } 93 | 94 | internal protocol Mavsdk_Rpc_ComponentInformationServer_ComponentInformationServerServiceClientInterceptorFactoryProtocol { 95 | 96 | /// - Returns: Interceptors to use when invoking 'provideFloatParam'. 97 | func makeProvideFloatParamInterceptors() -> [ClientInterceptor] 98 | 99 | /// - Returns: Interceptors to use when invoking 'subscribeFloatParam'. 100 | func makeSubscribeFloatParamInterceptors() -> [ClientInterceptor] 101 | } 102 | 103 | internal final class Mavsdk_Rpc_ComponentInformationServer_ComponentInformationServerServiceClient: Mavsdk_Rpc_ComponentInformationServer_ComponentInformationServerServiceClientProtocol { 104 | internal let channel: GRPCChannel 105 | internal var defaultCallOptions: CallOptions 106 | internal var interceptors: Mavsdk_Rpc_ComponentInformationServer_ComponentInformationServerServiceClientInterceptorFactoryProtocol? 107 | 108 | /// Creates a client for the mavsdk.rpc.component_information_server.ComponentInformationServerService service. 109 | /// 110 | /// - Parameters: 111 | /// - channel: `GRPCChannel` to the service host. 112 | /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. 113 | /// - interceptors: A factory providing interceptors for each RPC. 114 | internal init( 115 | channel: GRPCChannel, 116 | defaultCallOptions: CallOptions = CallOptions(), 117 | interceptors: Mavsdk_Rpc_ComponentInformationServer_ComponentInformationServerServiceClientInterceptorFactoryProtocol? = nil 118 | ) { 119 | self.channel = channel 120 | self.defaultCallOptions = defaultCallOptions 121 | self.interceptors = interceptors 122 | } 123 | } 124 | 125 | /// Provide component information such as parameters. 126 | /// 127 | /// To build a server, implement a class that conforms to this protocol. 128 | internal protocol Mavsdk_Rpc_ComponentInformationServer_ComponentInformationServerServiceProvider: CallHandlerProvider { 129 | var interceptors: Mavsdk_Rpc_ComponentInformationServer_ComponentInformationServerServiceServerInterceptorFactoryProtocol? { get } 130 | 131 | /// 132 | /// Provide a param of type float. 133 | func provideFloatParam(request: Mavsdk_Rpc_ComponentInformationServer_ProvideFloatParamRequest, context: StatusOnlyCallContext) -> EventLoopFuture 134 | 135 | /// 136 | /// Subscribe to float param updates. 137 | func subscribeFloatParam(request: Mavsdk_Rpc_ComponentInformationServer_SubscribeFloatParamRequest, context: StreamingResponseCallContext) -> EventLoopFuture 138 | } 139 | 140 | extension Mavsdk_Rpc_ComponentInformationServer_ComponentInformationServerServiceProvider { 141 | internal var serviceName: Substring { return "mavsdk.rpc.component_information_server.ComponentInformationServerService" } 142 | 143 | /// Determines, calls and returns the appropriate request handler, depending on the request's method. 144 | /// Returns nil for methods not handled by this service. 145 | internal func handle( 146 | method name: Substring, 147 | context: CallHandlerContext 148 | ) -> GRPCServerHandlerProtocol? { 149 | switch name { 150 | case "ProvideFloatParam": 151 | return UnaryServerHandler( 152 | context: context, 153 | requestDeserializer: ProtobufDeserializer(), 154 | responseSerializer: ProtobufSerializer(), 155 | interceptors: self.interceptors?.makeProvideFloatParamInterceptors() ?? [], 156 | userFunction: self.provideFloatParam(request:context:) 157 | ) 158 | 159 | case "SubscribeFloatParam": 160 | return ServerStreamingServerHandler( 161 | context: context, 162 | requestDeserializer: ProtobufDeserializer(), 163 | responseSerializer: ProtobufSerializer(), 164 | interceptors: self.interceptors?.makeSubscribeFloatParamInterceptors() ?? [], 165 | userFunction: self.subscribeFloatParam(request:context:) 166 | ) 167 | 168 | default: 169 | return nil 170 | } 171 | } 172 | } 173 | 174 | internal protocol Mavsdk_Rpc_ComponentInformationServer_ComponentInformationServerServiceServerInterceptorFactoryProtocol { 175 | 176 | /// - Returns: Interceptors to use when handling 'provideFloatParam'. 177 | /// Defaults to calling `self.makeInterceptors()`. 178 | func makeProvideFloatParamInterceptors() -> [ServerInterceptor] 179 | 180 | /// - Returns: Interceptors to use when handling 'subscribeFloatParam'. 181 | /// Defaults to calling `self.makeInterceptors()`. 182 | func makeSubscribeFloatParamInterceptors() -> [ServerInterceptor] 183 | } 184 | -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/core.pb.swift: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT. 2 | // swift-format-ignore-file 3 | // 4 | // Generated by the Swift generator plugin for the protocol buffer compiler. 5 | // Source: core.proto 6 | // 7 | // For information on using the generated types, please see the documentation: 8 | // https://github.com/apple/swift-protobuf/ 9 | 10 | import Foundation 11 | import SwiftProtobuf 12 | 13 | // If the compiler emits an error on this type, it is because this file 14 | // was generated by a version of the `protoc` Swift plug-in that is 15 | // incompatible with the version of SwiftProtobuf to which you are linking. 16 | // Please ensure that you are building against the same version of the API 17 | // that was used to generate this file. 18 | fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { 19 | struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} 20 | typealias Version = _2 21 | } 22 | 23 | struct Mavsdk_Rpc_Core_SubscribeConnectionStateRequest { 24 | // SwiftProtobuf.Message conformance is added in an extension below. See the 25 | // `Message` and `Message+*Additions` files in the SwiftProtobuf library for 26 | // methods supported on all messages. 27 | 28 | var unknownFields = SwiftProtobuf.UnknownStorage() 29 | 30 | init() {} 31 | } 32 | 33 | struct Mavsdk_Rpc_Core_ConnectionStateResponse { 34 | // SwiftProtobuf.Message conformance is added in an extension below. See the 35 | // `Message` and `Message+*Additions` files in the SwiftProtobuf library for 36 | // methods supported on all messages. 37 | 38 | /// Connection state 39 | var connectionState: Mavsdk_Rpc_Core_ConnectionState { 40 | get {return _connectionState ?? Mavsdk_Rpc_Core_ConnectionState()} 41 | set {_connectionState = newValue} 42 | } 43 | /// Returns true if `connectionState` has been explicitly set. 44 | var hasConnectionState: Bool {return self._connectionState != nil} 45 | /// Clears the value of `connectionState`. Subsequent reads from it will return its default value. 46 | mutating func clearConnectionState() {self._connectionState = nil} 47 | 48 | var unknownFields = SwiftProtobuf.UnknownStorage() 49 | 50 | init() {} 51 | 52 | fileprivate var _connectionState: Mavsdk_Rpc_Core_ConnectionState? = nil 53 | } 54 | 55 | struct Mavsdk_Rpc_Core_SetMavlinkTimeoutRequest { 56 | // SwiftProtobuf.Message conformance is added in an extension below. See the 57 | // `Message` and `Message+*Additions` files in the SwiftProtobuf library for 58 | // methods supported on all messages. 59 | 60 | /// Timeout in seconds 61 | var timeoutS: Double = 0 62 | 63 | var unknownFields = SwiftProtobuf.UnknownStorage() 64 | 65 | init() {} 66 | } 67 | 68 | struct Mavsdk_Rpc_Core_SetMavlinkTimeoutResponse { 69 | // SwiftProtobuf.Message conformance is added in an extension below. See the 70 | // `Message` and `Message+*Additions` files in the SwiftProtobuf library for 71 | // methods supported on all messages. 72 | 73 | var unknownFields = SwiftProtobuf.UnknownStorage() 74 | 75 | init() {} 76 | } 77 | 78 | /// Connection state type. 79 | struct Mavsdk_Rpc_Core_ConnectionState { 80 | // SwiftProtobuf.Message conformance is added in an extension below. See the 81 | // `Message` and `Message+*Additions` files in the SwiftProtobuf library for 82 | // methods supported on all messages. 83 | 84 | /// Whether the vehicle got connected or disconnected 85 | var isConnected: Bool = false 86 | 87 | var unknownFields = SwiftProtobuf.UnknownStorage() 88 | 89 | init() {} 90 | } 91 | 92 | #if swift(>=5.5) && canImport(_Concurrency) 93 | extension Mavsdk_Rpc_Core_SubscribeConnectionStateRequest: @unchecked Sendable {} 94 | extension Mavsdk_Rpc_Core_ConnectionStateResponse: @unchecked Sendable {} 95 | extension Mavsdk_Rpc_Core_SetMavlinkTimeoutRequest: @unchecked Sendable {} 96 | extension Mavsdk_Rpc_Core_SetMavlinkTimeoutResponse: @unchecked Sendable {} 97 | extension Mavsdk_Rpc_Core_ConnectionState: @unchecked Sendable {} 98 | #endif // swift(>=5.5) && canImport(_Concurrency) 99 | 100 | // MARK: - Code below here is support for the SwiftProtobuf runtime. 101 | 102 | fileprivate let _protobuf_package = "mavsdk.rpc.core" 103 | 104 | extension Mavsdk_Rpc_Core_SubscribeConnectionStateRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 105 | static let protoMessageName: String = _protobuf_package + ".SubscribeConnectionStateRequest" 106 | static let _protobuf_nameMap = SwiftProtobuf._NameMap() 107 | 108 | mutating func decodeMessage(decoder: inout D) throws { 109 | while let _ = try decoder.nextFieldNumber() { 110 | } 111 | } 112 | 113 | func traverse(visitor: inout V) throws { 114 | try unknownFields.traverse(visitor: &visitor) 115 | } 116 | 117 | static func ==(lhs: Mavsdk_Rpc_Core_SubscribeConnectionStateRequest, rhs: Mavsdk_Rpc_Core_SubscribeConnectionStateRequest) -> Bool { 118 | if lhs.unknownFields != rhs.unknownFields {return false} 119 | return true 120 | } 121 | } 122 | 123 | extension Mavsdk_Rpc_Core_ConnectionStateResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 124 | static let protoMessageName: String = _protobuf_package + ".ConnectionStateResponse" 125 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 126 | 1: .standard(proto: "connection_state"), 127 | ] 128 | 129 | mutating func decodeMessage(decoder: inout D) throws { 130 | while let fieldNumber = try decoder.nextFieldNumber() { 131 | // The use of inline closures is to circumvent an issue where the compiler 132 | // allocates stack space for every case branch when no optimizations are 133 | // enabled. https://github.com/apple/swift-protobuf/issues/1034 134 | switch fieldNumber { 135 | case 1: try { try decoder.decodeSingularMessageField(value: &self._connectionState) }() 136 | default: break 137 | } 138 | } 139 | } 140 | 141 | func traverse(visitor: inout V) throws { 142 | // The use of inline closures is to circumvent an issue where the compiler 143 | // allocates stack space for every if/case branch local when no optimizations 144 | // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and 145 | // https://github.com/apple/swift-protobuf/issues/1182 146 | try { if let v = self._connectionState { 147 | try visitor.visitSingularMessageField(value: v, fieldNumber: 1) 148 | } }() 149 | try unknownFields.traverse(visitor: &visitor) 150 | } 151 | 152 | static func ==(lhs: Mavsdk_Rpc_Core_ConnectionStateResponse, rhs: Mavsdk_Rpc_Core_ConnectionStateResponse) -> Bool { 153 | if lhs._connectionState != rhs._connectionState {return false} 154 | if lhs.unknownFields != rhs.unknownFields {return false} 155 | return true 156 | } 157 | } 158 | 159 | extension Mavsdk_Rpc_Core_SetMavlinkTimeoutRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 160 | static let protoMessageName: String = _protobuf_package + ".SetMavlinkTimeoutRequest" 161 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 162 | 1: .standard(proto: "timeout_s"), 163 | ] 164 | 165 | mutating func decodeMessage(decoder: inout D) throws { 166 | while let fieldNumber = try decoder.nextFieldNumber() { 167 | // The use of inline closures is to circumvent an issue where the compiler 168 | // allocates stack space for every case branch when no optimizations are 169 | // enabled. https://github.com/apple/swift-protobuf/issues/1034 170 | switch fieldNumber { 171 | case 1: try { try decoder.decodeSingularDoubleField(value: &self.timeoutS) }() 172 | default: break 173 | } 174 | } 175 | } 176 | 177 | func traverse(visitor: inout V) throws { 178 | if self.timeoutS != 0 { 179 | try visitor.visitSingularDoubleField(value: self.timeoutS, fieldNumber: 1) 180 | } 181 | try unknownFields.traverse(visitor: &visitor) 182 | } 183 | 184 | static func ==(lhs: Mavsdk_Rpc_Core_SetMavlinkTimeoutRequest, rhs: Mavsdk_Rpc_Core_SetMavlinkTimeoutRequest) -> Bool { 185 | if lhs.timeoutS != rhs.timeoutS {return false} 186 | if lhs.unknownFields != rhs.unknownFields {return false} 187 | return true 188 | } 189 | } 190 | 191 | extension Mavsdk_Rpc_Core_SetMavlinkTimeoutResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 192 | static let protoMessageName: String = _protobuf_package + ".SetMavlinkTimeoutResponse" 193 | static let _protobuf_nameMap = SwiftProtobuf._NameMap() 194 | 195 | mutating func decodeMessage(decoder: inout D) throws { 196 | while let _ = try decoder.nextFieldNumber() { 197 | } 198 | } 199 | 200 | func traverse(visitor: inout V) throws { 201 | try unknownFields.traverse(visitor: &visitor) 202 | } 203 | 204 | static func ==(lhs: Mavsdk_Rpc_Core_SetMavlinkTimeoutResponse, rhs: Mavsdk_Rpc_Core_SetMavlinkTimeoutResponse) -> Bool { 205 | if lhs.unknownFields != rhs.unknownFields {return false} 206 | return true 207 | } 208 | } 209 | 210 | extension Mavsdk_Rpc_Core_ConnectionState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { 211 | static let protoMessageName: String = _protobuf_package + ".ConnectionState" 212 | static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ 213 | 2: .standard(proto: "is_connected"), 214 | ] 215 | 216 | mutating func decodeMessage(decoder: inout D) throws { 217 | while let fieldNumber = try decoder.nextFieldNumber() { 218 | // The use of inline closures is to circumvent an issue where the compiler 219 | // allocates stack space for every case branch when no optimizations are 220 | // enabled. https://github.com/apple/swift-protobuf/issues/1034 221 | switch fieldNumber { 222 | case 2: try { try decoder.decodeSingularBoolField(value: &self.isConnected) }() 223 | default: break 224 | } 225 | } 226 | } 227 | 228 | func traverse(visitor: inout V) throws { 229 | if self.isConnected != false { 230 | try visitor.visitSingularBoolField(value: self.isConnected, fieldNumber: 2) 231 | } 232 | try unknownFields.traverse(visitor: &visitor) 233 | } 234 | 235 | static func ==(lhs: Mavsdk_Rpc_Core_ConnectionState, rhs: Mavsdk_Rpc_Core_ConnectionState) -> Bool { 236 | if lhs.isConnected != rhs.isConnected {return false} 237 | if lhs.unknownFields != rhs.unknownFields {return false} 238 | return true 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/mocap.grpc.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DO NOT EDIT. 3 | // 4 | // Generated by the protocol buffer compiler. 5 | // Source: mocap.proto 6 | // 7 | 8 | // 9 | // Copyright 2018, gRPC Authors All rights reserved. 10 | // 11 | // Licensed under the Apache License, Version 2.0 (the "License"); 12 | // you may not use this file except in compliance with the License. 13 | // You may obtain a copy of the License at 14 | // 15 | // http://www.apache.org/licenses/LICENSE-2.0 16 | // 17 | // Unless required by applicable law or agreed to in writing, software 18 | // distributed under the License is distributed on an "AS IS" BASIS, 19 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | // See the License for the specific language governing permissions and 21 | // limitations under the License. 22 | // 23 | import GRPC 24 | import NIO 25 | import SwiftProtobuf 26 | 27 | 28 | ///* 29 | /// Allows interfacing a vehicle with a motion capture system in 30 | /// order to allow navigation without global positioning sources available 31 | /// (e.g. indoors, or when flying under a bridge. etc.). 32 | /// 33 | /// Usage: instantiate `Mavsdk_Rpc_Mocap_MocapServiceClient`, then call methods of this protocol to make API calls. 34 | internal protocol Mavsdk_Rpc_Mocap_MocapServiceClientProtocol: GRPCClient { 35 | var serviceName: String { get } 36 | var interceptors: Mavsdk_Rpc_Mocap_MocapServiceClientInterceptorFactoryProtocol? { get } 37 | 38 | func setVisionPositionEstimate( 39 | _ request: Mavsdk_Rpc_Mocap_SetVisionPositionEstimateRequest, 40 | callOptions: CallOptions? 41 | ) -> UnaryCall 42 | 43 | func setAttitudePositionMocap( 44 | _ request: Mavsdk_Rpc_Mocap_SetAttitudePositionMocapRequest, 45 | callOptions: CallOptions? 46 | ) -> UnaryCall 47 | 48 | func setOdometry( 49 | _ request: Mavsdk_Rpc_Mocap_SetOdometryRequest, 50 | callOptions: CallOptions? 51 | ) -> UnaryCall 52 | } 53 | 54 | extension Mavsdk_Rpc_Mocap_MocapServiceClientProtocol { 55 | internal var serviceName: String { 56 | return "mavsdk.rpc.mocap.MocapService" 57 | } 58 | 59 | /// Send Global position/attitude estimate from a vision source. 60 | /// 61 | /// - Parameters: 62 | /// - request: Request to send to SetVisionPositionEstimate. 63 | /// - callOptions: Call options. 64 | /// - Returns: A `UnaryCall` with futures for the metadata, status and response. 65 | internal func setVisionPositionEstimate( 66 | _ request: Mavsdk_Rpc_Mocap_SetVisionPositionEstimateRequest, 67 | callOptions: CallOptions? = nil 68 | ) -> UnaryCall { 69 | return self.makeUnaryCall( 70 | path: "/mavsdk.rpc.mocap.MocapService/SetVisionPositionEstimate", 71 | request: request, 72 | callOptions: callOptions ?? self.defaultCallOptions, 73 | interceptors: self.interceptors?.makeSetVisionPositionEstimateInterceptors() ?? [] 74 | ) 75 | } 76 | 77 | /// Send motion capture attitude and position. 78 | /// 79 | /// - Parameters: 80 | /// - request: Request to send to SetAttitudePositionMocap. 81 | /// - callOptions: Call options. 82 | /// - Returns: A `UnaryCall` with futures for the metadata, status and response. 83 | internal func setAttitudePositionMocap( 84 | _ request: Mavsdk_Rpc_Mocap_SetAttitudePositionMocapRequest, 85 | callOptions: CallOptions? = nil 86 | ) -> UnaryCall { 87 | return self.makeUnaryCall( 88 | path: "/mavsdk.rpc.mocap.MocapService/SetAttitudePositionMocap", 89 | request: request, 90 | callOptions: callOptions ?? self.defaultCallOptions, 91 | interceptors: self.interceptors?.makeSetAttitudePositionMocapInterceptors() ?? [] 92 | ) 93 | } 94 | 95 | /// Send odometry information with an external interface. 96 | /// 97 | /// - Parameters: 98 | /// - request: Request to send to SetOdometry. 99 | /// - callOptions: Call options. 100 | /// - Returns: A `UnaryCall` with futures for the metadata, status and response. 101 | internal func setOdometry( 102 | _ request: Mavsdk_Rpc_Mocap_SetOdometryRequest, 103 | callOptions: CallOptions? = nil 104 | ) -> UnaryCall { 105 | return self.makeUnaryCall( 106 | path: "/mavsdk.rpc.mocap.MocapService/SetOdometry", 107 | request: request, 108 | callOptions: callOptions ?? self.defaultCallOptions, 109 | interceptors: self.interceptors?.makeSetOdometryInterceptors() ?? [] 110 | ) 111 | } 112 | } 113 | 114 | internal protocol Mavsdk_Rpc_Mocap_MocapServiceClientInterceptorFactoryProtocol { 115 | 116 | /// - Returns: Interceptors to use when invoking 'setVisionPositionEstimate'. 117 | func makeSetVisionPositionEstimateInterceptors() -> [ClientInterceptor] 118 | 119 | /// - Returns: Interceptors to use when invoking 'setAttitudePositionMocap'. 120 | func makeSetAttitudePositionMocapInterceptors() -> [ClientInterceptor] 121 | 122 | /// - Returns: Interceptors to use when invoking 'setOdometry'. 123 | func makeSetOdometryInterceptors() -> [ClientInterceptor] 124 | } 125 | 126 | internal final class Mavsdk_Rpc_Mocap_MocapServiceClient: Mavsdk_Rpc_Mocap_MocapServiceClientProtocol { 127 | internal let channel: GRPCChannel 128 | internal var defaultCallOptions: CallOptions 129 | internal var interceptors: Mavsdk_Rpc_Mocap_MocapServiceClientInterceptorFactoryProtocol? 130 | 131 | /// Creates a client for the mavsdk.rpc.mocap.MocapService service. 132 | /// 133 | /// - Parameters: 134 | /// - channel: `GRPCChannel` to the service host. 135 | /// - defaultCallOptions: Options to use for each service call if the user doesn't provide them. 136 | /// - interceptors: A factory providing interceptors for each RPC. 137 | internal init( 138 | channel: GRPCChannel, 139 | defaultCallOptions: CallOptions = CallOptions(), 140 | interceptors: Mavsdk_Rpc_Mocap_MocapServiceClientInterceptorFactoryProtocol? = nil 141 | ) { 142 | self.channel = channel 143 | self.defaultCallOptions = defaultCallOptions 144 | self.interceptors = interceptors 145 | } 146 | } 147 | 148 | ///* 149 | /// Allows interfacing a vehicle with a motion capture system in 150 | /// order to allow navigation without global positioning sources available 151 | /// (e.g. indoors, or when flying under a bridge. etc.). 152 | /// 153 | /// To build a server, implement a class that conforms to this protocol. 154 | internal protocol Mavsdk_Rpc_Mocap_MocapServiceProvider: CallHandlerProvider { 155 | var interceptors: Mavsdk_Rpc_Mocap_MocapServiceServerInterceptorFactoryProtocol? { get } 156 | 157 | /// Send Global position/attitude estimate from a vision source. 158 | func setVisionPositionEstimate(request: Mavsdk_Rpc_Mocap_SetVisionPositionEstimateRequest, context: StatusOnlyCallContext) -> EventLoopFuture 159 | 160 | /// Send motion capture attitude and position. 161 | func setAttitudePositionMocap(request: Mavsdk_Rpc_Mocap_SetAttitudePositionMocapRequest, context: StatusOnlyCallContext) -> EventLoopFuture 162 | 163 | /// Send odometry information with an external interface. 164 | func setOdometry(request: Mavsdk_Rpc_Mocap_SetOdometryRequest, context: StatusOnlyCallContext) -> EventLoopFuture 165 | } 166 | 167 | extension Mavsdk_Rpc_Mocap_MocapServiceProvider { 168 | internal var serviceName: Substring { return "mavsdk.rpc.mocap.MocapService" } 169 | 170 | /// Determines, calls and returns the appropriate request handler, depending on the request's method. 171 | /// Returns nil for methods not handled by this service. 172 | internal func handle( 173 | method name: Substring, 174 | context: CallHandlerContext 175 | ) -> GRPCServerHandlerProtocol? { 176 | switch name { 177 | case "SetVisionPositionEstimate": 178 | return UnaryServerHandler( 179 | context: context, 180 | requestDeserializer: ProtobufDeserializer(), 181 | responseSerializer: ProtobufSerializer(), 182 | interceptors: self.interceptors?.makeSetVisionPositionEstimateInterceptors() ?? [], 183 | userFunction: self.setVisionPositionEstimate(request:context:) 184 | ) 185 | 186 | case "SetAttitudePositionMocap": 187 | return UnaryServerHandler( 188 | context: context, 189 | requestDeserializer: ProtobufDeserializer(), 190 | responseSerializer: ProtobufSerializer(), 191 | interceptors: self.interceptors?.makeSetAttitudePositionMocapInterceptors() ?? [], 192 | userFunction: self.setAttitudePositionMocap(request:context:) 193 | ) 194 | 195 | case "SetOdometry": 196 | return UnaryServerHandler( 197 | context: context, 198 | requestDeserializer: ProtobufDeserializer(), 199 | responseSerializer: ProtobufSerializer(), 200 | interceptors: self.interceptors?.makeSetOdometryInterceptors() ?? [], 201 | userFunction: self.setOdometry(request:context:) 202 | ) 203 | 204 | default: 205 | return nil 206 | } 207 | } 208 | } 209 | 210 | internal protocol Mavsdk_Rpc_Mocap_MocapServiceServerInterceptorFactoryProtocol { 211 | 212 | /// - Returns: Interceptors to use when handling 'setVisionPositionEstimate'. 213 | /// Defaults to calling `self.makeInterceptors()`. 214 | func makeSetVisionPositionEstimateInterceptors() -> [ServerInterceptor] 215 | 216 | /// - Returns: Interceptors to use when handling 'setAttitudePositionMocap'. 217 | /// Defaults to calling `self.makeInterceptors()`. 218 | func makeSetAttitudePositionMocapInterceptors() -> [ServerInterceptor] 219 | 220 | /// - Returns: Interceptors to use when handling 'setOdometry'. 221 | /// Defaults to calling `self.makeInterceptors()`. 222 | func makeSetOdometryInterceptors() -> [ServerInterceptor] 223 | } 224 | -------------------------------------------------------------------------------- /Sources/Mavsdk/Generated/ManualControl.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import RxSwift 3 | import GRPC 4 | import NIO 5 | 6 | /** 7 | Enable manual control using e.g. a joystick or gamepad. 8 | */ 9 | public class ManualControl { 10 | private let service: Mavsdk_Rpc_ManualControl_ManualControlServiceClient 11 | private let scheduler: SchedulerType 12 | private let clientEventLoopGroup: EventLoopGroup 13 | 14 | /** 15 | Initializes a new `ManualControl` plugin. 16 | 17 | Normally never created manually, but used from the `Drone` helper class instead. 18 | 19 | - Parameters: 20 | - address: The address of the `MavsdkServer` instance to connect to 21 | - port: The port of the `MavsdkServer` instance to connect to 22 | - scheduler: The scheduler to be used by `Observable`s 23 | */ 24 | public convenience init(address: String = "localhost", 25 | port: Int32 = 50051, 26 | scheduler: SchedulerType = ConcurrentDispatchQueueScheduler(qos: .background)) { 27 | let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 2) 28 | let channel = ClientConnection.insecure(group: eventLoopGroup).connect(host: address, port: Int(port)) 29 | let service = Mavsdk_Rpc_ManualControl_ManualControlServiceClient(channel: channel) 30 | 31 | self.init(service: service, scheduler: scheduler, eventLoopGroup: eventLoopGroup) 32 | } 33 | 34 | init(service: Mavsdk_Rpc_ManualControl_ManualControlServiceClient, scheduler: SchedulerType, eventLoopGroup: EventLoopGroup) { 35 | self.service = service 36 | self.scheduler = scheduler 37 | self.clientEventLoopGroup = eventLoopGroup 38 | } 39 | 40 | public struct RuntimeManualControlError: Error { 41 | public let description: String 42 | 43 | init(_ description: String) { 44 | self.description = description 45 | } 46 | } 47 | 48 | 49 | public struct ManualControlError: Error { 50 | public let code: ManualControl.ManualControlResult.Result 51 | public let description: String 52 | } 53 | 54 | 55 | 56 | /** 57 | Result type. 58 | */ 59 | public struct ManualControlResult: Equatable { 60 | public let result: Result 61 | public let resultStr: String 62 | 63 | 64 | 65 | 66 | /** 67 | Possible results returned for manual control requests. 68 | */ 69 | public enum Result: Equatable { 70 | /// Unknown result. 71 | case unknown 72 | /// Request was successful. 73 | case success 74 | /// No system is connected. 75 | case noSystem 76 | /// Connection error. 77 | case connectionError 78 | /// Vehicle is busy. 79 | case busy 80 | /// Command refused by vehicle. 81 | case commandDenied 82 | /// Request timed out. 83 | case timeout 84 | /// Input out of range. 85 | case inputOutOfRange 86 | /// No Input set. 87 | case inputNotSet 88 | case UNRECOGNIZED(Int) 89 | 90 | internal var rpcResult: Mavsdk_Rpc_ManualControl_ManualControlResult.Result { 91 | switch self { 92 | case .unknown: 93 | return .unknown 94 | case .success: 95 | return .success 96 | case .noSystem: 97 | return .noSystem 98 | case .connectionError: 99 | return .connectionError 100 | case .busy: 101 | return .busy 102 | case .commandDenied: 103 | return .commandDenied 104 | case .timeout: 105 | return .timeout 106 | case .inputOutOfRange: 107 | return .inputOutOfRange 108 | case .inputNotSet: 109 | return .inputNotSet 110 | case .UNRECOGNIZED(let i): 111 | return .UNRECOGNIZED(i) 112 | } 113 | } 114 | 115 | internal static func translateFromRpc(_ rpcResult: Mavsdk_Rpc_ManualControl_ManualControlResult.Result) -> Result { 116 | switch rpcResult { 117 | case .unknown: 118 | return .unknown 119 | case .success: 120 | return .success 121 | case .noSystem: 122 | return .noSystem 123 | case .connectionError: 124 | return .connectionError 125 | case .busy: 126 | return .busy 127 | case .commandDenied: 128 | return .commandDenied 129 | case .timeout: 130 | return .timeout 131 | case .inputOutOfRange: 132 | return .inputOutOfRange 133 | case .inputNotSet: 134 | return .inputNotSet 135 | case .UNRECOGNIZED(let i): 136 | return .UNRECOGNIZED(i) 137 | } 138 | } 139 | } 140 | 141 | 142 | /** 143 | Initializes a new `ManualControlResult`. 144 | 145 | 146 | - Parameters: 147 | 148 | - result: Result enum value 149 | 150 | - resultStr: Human-readable English string describing the result 151 | 152 | 153 | */ 154 | public init(result: Result, resultStr: String) { 155 | self.result = result 156 | self.resultStr = resultStr 157 | } 158 | 159 | internal var rpcManualControlResult: Mavsdk_Rpc_ManualControl_ManualControlResult { 160 | var rpcManualControlResult = Mavsdk_Rpc_ManualControl_ManualControlResult() 161 | 162 | 163 | rpcManualControlResult.result = result.rpcResult 164 | 165 | 166 | 167 | 168 | rpcManualControlResult.resultStr = resultStr 169 | 170 | 171 | 172 | return rpcManualControlResult 173 | } 174 | 175 | internal static func translateFromRpc(_ rpcManualControlResult: Mavsdk_Rpc_ManualControl_ManualControlResult) -> ManualControlResult { 176 | return ManualControlResult(result: Result.translateFromRpc(rpcManualControlResult.result), resultStr: rpcManualControlResult.resultStr) 177 | } 178 | 179 | public static func == (lhs: ManualControlResult, rhs: ManualControlResult) -> Bool { 180 | return lhs.result == rhs.result 181 | && lhs.resultStr == rhs.resultStr 182 | } 183 | } 184 | 185 | 186 | /** 187 | Start position control using e.g. joystick input. 188 | 189 | Requires manual control input to be sent regularly already. 190 | Requires a valid position using e.g. GPS, external vision, or optical flow. 191 | 192 | 193 | */ 194 | public func startPositionControl() -> Completable { 195 | return Completable.create { completable in 196 | let request = Mavsdk_Rpc_ManualControl_StartPositionControlRequest() 197 | 198 | 199 | 200 | do { 201 | 202 | let response = self.service.startPositionControl(request) 203 | 204 | let result = try response.response.wait().manualControlResult 205 | if (result.result == Mavsdk_Rpc_ManualControl_ManualControlResult.Result.success) { 206 | completable(.completed) 207 | } else { 208 | completable(.error(ManualControlError(code: ManualControlResult.Result.translateFromRpc(result.result), description: result.resultStr))) 209 | } 210 | 211 | } catch { 212 | completable(.error(error)) 213 | } 214 | 215 | return Disposables.create() 216 | } 217 | } 218 | 219 | /** 220 | Start altitude control 221 | 222 | Requires manual control input to be sent regularly already. 223 | Does not require a valid position e.g. GPS. 224 | 225 | 226 | */ 227 | public func startAltitudeControl() -> Completable { 228 | return Completable.create { completable in 229 | let request = Mavsdk_Rpc_ManualControl_StartAltitudeControlRequest() 230 | 231 | 232 | 233 | do { 234 | 235 | let response = self.service.startAltitudeControl(request) 236 | 237 | let result = try response.response.wait().manualControlResult 238 | if (result.result == Mavsdk_Rpc_ManualControl_ManualControlResult.Result.success) { 239 | completable(.completed) 240 | } else { 241 | completable(.error(ManualControlError(code: ManualControlResult.Result.translateFromRpc(result.result), description: result.resultStr))) 242 | } 243 | 244 | } catch { 245 | completable(.error(error)) 246 | } 247 | 248 | return Disposables.create() 249 | } 250 | } 251 | 252 | /** 253 | Set manual control input 254 | 255 | The manual control input needs to be sent at a rate high enough to prevent 256 | triggering of RC loss, a good minimum rate is 10 Hz. 257 | 258 | - Parameters: 259 | - x: value between -1. to 1. negative -> backwards, positive -> forwards 260 | - y: value between -1. to 1. negative -> left, positive -> right 261 | - z: value between -1. to 1. negative -> down, positive -> up (usually for now, for multicopter 0 to 1 is expected) 262 | - r: value between -1. to 1. negative -> turn anti-clockwise (towards the left), positive -> turn clockwise (towards the right) 263 | 264 | */ 265 | public func setManualControlInput(x: Float, y: Float, z: Float, r: Float) -> Completable { 266 | return Completable.create { completable in 267 | var request = Mavsdk_Rpc_ManualControl_SetManualControlInputRequest() 268 | 269 | 270 | 271 | request.x = x 272 | 273 | 274 | 275 | request.y = y 276 | 277 | 278 | 279 | request.z = z 280 | 281 | 282 | 283 | request.r = r 284 | 285 | 286 | 287 | do { 288 | 289 | let response = self.service.setManualControlInput(request) 290 | 291 | let result = try response.response.wait().manualControlResult 292 | if (result.result == Mavsdk_Rpc_ManualControl_ManualControlResult.Result.success) { 293 | completable(.completed) 294 | } else { 295 | completable(.error(ManualControlError(code: ManualControlResult.Result.translateFromRpc(result.result), description: result.resultStr))) 296 | } 297 | 298 | } catch { 299 | completable(.error(error)) 300 | } 301 | 302 | return Disposables.create() 303 | } 304 | } 305 | } -------------------------------------------------------------------------------- /Tests/MavsdkTests/MissionTest.swift: -------------------------------------------------------------------------------- 1 | //import XCTest 2 | //import RxBlocking 3 | //import RxSwift 4 | //import RxTest 5 | //@testable import Mavsdk 6 | // 7 | //class MissionTest: XCTestCase { 8 | // 9 | // let missionResultsArary: [Mavsdk_Rpc_Mission_MissionResult.Result] = [.unknown, .error, .tooManyMissionItems, .busy, .timeout, .invalidArgument, .unsupported, .noMissionAvailable, .failedToOpenQgcPlan, .failedToParseQgcPlan, .unsupportedMissionCmd] 10 | // 11 | // func testUploadsOneItem() { 12 | // let fakeService = Mavsdk_Rpc_Mission_MissionServiceServiceTestStub() 13 | // let scheduler = TestScheduler(initialClock: 0) 14 | // let mission = Mission(service: fakeService, scheduler: scheduler) 15 | // 16 | // let missionItem = Mission.MissionItem(latitudeDeg: 46, longitudeDeg: 6, relativeAltitudeM: 50, speedMS: 3.4, isFlyThrough: true, gimbalPitchDeg: 90, gimbalYawDeg: 23, cameraAction: Mission.MissionItem.CameraAction.none, loiterTimeS: 2, cameraPhotoIntervalS: 1) 17 | // 18 | // _ = mission.uploadMission(missionItems: [missionItem]) 19 | // } 20 | // 21 | // func testDownloadMissionSucceedsOnSuccess() { 22 | // let expectedResult = [Mission.MissionItem(latitudeDeg: 46.0, longitudeDeg: 6.0, relativeAltitudeM: Float(50), speedMS: Float(3.4), isFlyThrough: true, gimbalPitchDeg: Float(90), gimbalYawDeg: Float(23), cameraAction: Mission.MissionItem.CameraAction.none, loiterTimeS: Float(2), cameraPhotoIntervalS: 1).rpcMissionItem] 23 | // 24 | // let fakeService = Mavsdk_Rpc_Mission_MissionServiceServiceTestStub() 25 | // var response = Mavsdk_Rpc_Mission_DownloadMissionResponse() 26 | // response.missionResult.result = Mavsdk_Rpc_Mission_MissionResult.Result.success 27 | // response.missionItems = expectedResult 28 | // 29 | // fakeService.downloadMissionResponses.append(response) 30 | // 31 | // let scheduler = TestScheduler(initialClock: 0) 32 | // let client = Mission(service: fakeService, scheduler: scheduler) 33 | // 34 | // _ = client.downloadMission() 35 | // .do(onError: { error in XCTFail("\(error)") }) 36 | // .subscribe() 37 | // } 38 | // 39 | // func testStartSucceedsOnSuccess() throws { 40 | // _ = try startWithFakeResult(result: Mavsdk_Rpc_Mission_MissionResult.Result.success) 41 | // } 42 | // 43 | // func startWithFakeResult(result: Mavsdk_Rpc_Mission_MissionResult.Result) throws { 44 | // let fakeService = Mavsdk_Rpc_Mission_MissionServiceServiceTestStub() 45 | // var response = Mavsdk_Rpc_Mission_StartMissionResponse() 46 | // response.missionResult.result = result 47 | // fakeService.startMissionResponses.append(response) 48 | // 49 | // let scheduler = TestScheduler(initialClock: 0) 50 | // let mission = Mission(service: fakeService, scheduler: scheduler) 51 | // 52 | // _ = mission.startMission().toBlocking().materialize() 53 | // } 54 | // 55 | // func testStartFailsOnFailure() throws { 56 | // try missionResultsArary.forEach { result in 57 | // try startWithFakeResult(result: result) 58 | // } 59 | // } 60 | // 61 | // func testPauseSucceedsOnSuccess() throws { 62 | // try pauseWithFakeResult(result: Mavsdk_Rpc_Mission_MissionResult.Result.success) 63 | // } 64 | // 65 | // func pauseWithFakeResult(result: Mavsdk_Rpc_Mission_MissionResult.Result) throws { 66 | // let fakeService = Mavsdk_Rpc_Mission_MissionServiceServiceTestStub() 67 | // var response = Mavsdk_Rpc_Mission_PauseMissionResponse() 68 | // response.missionResult.result = result 69 | // fakeService.pauseMissionResponses.append(response) 70 | // 71 | // let scheduler = TestScheduler(initialClock: 0) 72 | // let mission = Mission(service: fakeService, scheduler: scheduler) 73 | // _ = mission.pauseMission() 74 | // .toBlocking() 75 | // .materialize() 76 | // 77 | // scheduler.start() 78 | // } 79 | // 80 | // func testPauseFailsOnFailure() throws { 81 | // try missionResultsArary.forEach { result in 82 | // try pauseWithFakeResult(result: result) 83 | // } 84 | // } 85 | // 86 | // func testSetReturnToLaunchAfterMissionOnSuccess() throws { 87 | // _ = try setReturnToLaunchAfterMissionWithFakeResults() 88 | // } 89 | // 90 | // func setReturnToLaunchAfterMissionWithFakeResults() throws { 91 | // let fakeService = Mavsdk_Rpc_Mission_MissionServiceServiceTestStub() 92 | // let response = Mavsdk_Rpc_Mission_SetReturnToLaunchAfterMissionResponse() 93 | // fakeService.setReturnToLaunchAfterMissionResponses.append(response) 94 | // 95 | // let scheduler = TestScheduler(initialClock: 0) 96 | // let mission = Mission(service: fakeService, scheduler: scheduler) 97 | // 98 | // _ = mission.setReturnToLaunchAfterMission(enable: true).toBlocking().materialize() 99 | // } 100 | // 101 | // func testGetReturnToLaunchAfterMissionOnSuccess() { 102 | // let expectedValue = true 103 | // 104 | // let fakeService = Mavsdk_Rpc_Mission_MissionServiceServiceTestStub() 105 | // var response = Mavsdk_Rpc_Mission_GetReturnToLaunchAfterMissionResponse() 106 | // response.enable = expectedValue 107 | // fakeService.getReturnToLaunchAfterMissionResponses.append(response) 108 | // 109 | // let scheduler = TestScheduler(initialClock: 0) 110 | // let mission = Mission(service: fakeService, scheduler: scheduler) 111 | // 112 | // _ = mission.getReturnToLaunchAfterMission().subscribe { event in 113 | // switch event { 114 | // case .success(let index): 115 | // XCTAssert(index == expectedValue) 116 | // break 117 | // case .error(let error): 118 | // XCTFail("Expecting success, got failure: getReturnToLaunchAfterMission() \(error)") 119 | // } 120 | // } 121 | // } 122 | // 123 | // func testSetCurrentMissionItemIndexOnSuccess() throws { 124 | // _ = try setCurrentMissionItemIndexWithFakeResults() 125 | // } 126 | // 127 | // func setCurrentMissionItemIndexWithFakeResults() throws { 128 | // let fakeService = Mavsdk_Rpc_Mission_MissionServiceServiceTestStub() 129 | // let response = Mavsdk_Rpc_Mission_SetCurrentMissionItemIndexResponse() 130 | // fakeService.setCurrentMissionItemIndexResponses.append(response) 131 | // 132 | // let scheduler = TestScheduler(initialClock: 0) 133 | // let mission = Mission(service: fakeService, scheduler: scheduler) 134 | // 135 | // _ = mission.setCurrentMissionItemIndex(index: 2).toBlocking().materialize() 136 | // } 137 | // 138 | // func testIsMissionFinishedSucceedsOnSuccess() { 139 | // let expectedResult = true 140 | // let fakeService = Mavsdk_Rpc_Mission_MissionServiceServiceTestStub() 141 | // var response = Mavsdk_Rpc_Mission_IsMissionFinishedResponse() 142 | // response.isFinished = expectedResult 143 | // fakeService.isMissionFinishedResponses.append(response) 144 | // 145 | // let scheduler = TestScheduler(initialClock: 0) 146 | // let mission = Mission(service: fakeService, scheduler: scheduler) 147 | // 148 | // _ = mission.isMissionFinished().subscribe { event in 149 | // switch event { 150 | // case .success(let isFinished): 151 | // XCTAssert(isFinished == expectedResult) 152 | // break 153 | // case .error(let error): 154 | // XCTFail("Expecting success, got failure: isMissionFinished() \(error) ") 155 | // } 156 | // } 157 | // } 158 | // 159 | // func testMissionProgressObservableEmitsNothingWhenNoEvent() { 160 | // let fakeService = Mavsdk_Rpc_Mission_MissionServiceServiceTestStub() 161 | // let fakeCall = Mavsdk_Rpc_Mission_MissionServiceSubscribeMissionProgressCallTestStub() 162 | // fakeService.subscribeMissionProgressCalls.append(fakeCall) 163 | // 164 | // let scheduler = TestScheduler(initialClock: 0) 165 | // let mission = Mission(service: fakeService, scheduler: scheduler) 166 | // let observer = scheduler.createObserver(Mission.MissionProgress.self) 167 | // 168 | // let _ = mission.missionProgress.subscribe(observer) 169 | // scheduler.start() 170 | // 171 | // XCTAssertEqual(0, observer.events.count) 172 | // } 173 | // 174 | // func testMissionProgressObservableReceivesOneEvent() { 175 | // let missionProgress = createRPCMissionProgress(currentItemIndex: 5, missionCount: 10) 176 | // let missionProgressArray = [missionProgress] 177 | // 178 | // checkMissionProgressObservableReceivesEvents(missionProgressArray: missionProgressArray) 179 | // } 180 | // 181 | // func testMissionProgressObservableReceivesMultipleEvents() { 182 | // var missionProgressArray = [Mavsdk_Rpc_Mission_MissionProgressResponse]() 183 | // missionProgressArray.append(createRPCMissionProgress(currentItemIndex: 1, missionCount: 10)) 184 | // missionProgressArray.append(createRPCMissionProgress(currentItemIndex: 2, missionCount: 10)) 185 | // missionProgressArray.append(createRPCMissionProgress(currentItemIndex: 3, missionCount: 10)) 186 | // missionProgressArray.append(createRPCMissionProgress(currentItemIndex: 4, missionCount: 10)) 187 | // missionProgressArray.append(createRPCMissionProgress(currentItemIndex: 5, missionCount: 10)) 188 | // missionProgressArray.append(createRPCMissionProgress(currentItemIndex: 6, missionCount: 10)) 189 | // missionProgressArray.append(createRPCMissionProgress(currentItemIndex: 7, missionCount: 10)) 190 | // 191 | // checkMissionProgressObservableReceivesEvents(missionProgressArray: missionProgressArray) 192 | // } 193 | // 194 | // func checkMissionProgressObservableReceivesEvents(missionProgressArray: [Mavsdk_Rpc_Mission_MissionProgressResponse]) { 195 | // let fakeService = Mavsdk_Rpc_Mission_MissionServiceServiceTestStub() 196 | // let fakeCall = Mavsdk_Rpc_Mission_MissionServiceSubscribeMissionProgressCallTestStub() 197 | // 198 | // for missionProgress in missionProgressArray { 199 | // fakeCall.outputs.append(missionProgress) 200 | // } 201 | // fakeService.subscribeMissionProgressCalls.append(fakeCall) 202 | // 203 | // let scheduler = TestScheduler(initialClock: 0) 204 | // let mission = Mission(service: fakeService, scheduler: scheduler) 205 | // let observer = scheduler.createObserver(Mission.MissionProgress.self) 206 | // 207 | // let _ = mission.missionProgress.subscribe(observer) 208 | // scheduler.start() 209 | // 210 | // var expectedEvents = [Recorded>]() 211 | // for missionProgress in missionProgressArray { 212 | // expectedEvents.append(next(0, Mission.MissionProgress.translateFromRpc(missionProgress.missionProgress))) 213 | // } 214 | // 215 | // XCTAssertEqual(expectedEvents.count, observer.events.count) 216 | // XCTAssertTrue(observer.events.elementsEqual(expectedEvents, by: { (observed, expected) in 217 | // observed.value == expected.value 218 | // })) 219 | // } 220 | // 221 | // func createRPCMissionProgress(currentItemIndex: Int32, missionCount: Int32) -> Mavsdk_Rpc_Mission_MissionProgressResponse { 222 | // var response = Mavsdk_Rpc_Mission_MissionProgressResponse() 223 | // response.missionProgress.currentItemIndex = currentItemIndex 224 | // response.missionProgress.missionCount = missionCount 225 | // 226 | // return response 227 | // } 228 | //} 229 | --------------------------------------------------------------------------------