diff --git a/Shimmer.xcworkspace/contents.xcworkspacedata b/Shimmer.xcworkspace/contents.xcworkspacedata index 2d8f159..45b57e2 100644 --- a/Shimmer.xcworkspace/contents.xcworkspacedata +++ b/Shimmer.xcworkspace/contents.xcworkspacedata @@ -1,6 +1,9 @@ + + diff --git a/ShimmerBLEGrpc/Package.resolved b/ShimmerBLEGrpc/Package.resolved new file mode 100644 index 0000000..3fa9cb0 --- /dev/null +++ b/ShimmerBLEGrpc/Package.resolved @@ -0,0 +1,159 @@ +{ + "originHash" : "2587735e4e75b1e7432b81355b6e9f6393d7831ce12d12f713d63e706b91fc9c", + "pins" : [ + { + "identity" : "grpc-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/grpc/grpc-swift.git", + "state" : { + "revision" : "c4d6281784f50bf2e60d3af45e83be1194056062", + "version" : "2.1.2" + } + }, + { + "identity" : "grpc-swift-nio-transport", + "kind" : "remoteSourceControl", + "location" : "https://github.com/grpc/grpc-swift-nio-transport.git", + "state" : { + "revision" : "9bd1b5b5e31f3fae497e84c2806777899183679b", + "version" : "1.0.3" + } + }, + { + "identity" : "grpc-swift-protobuf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/grpc/grpc-swift-protobuf.git", + "state" : { + "revision" : "63982ca29f11d2c6a7e559c1899fee812dd55cd9", + "version" : "1.1.0" + } + }, + { + "identity" : "swift-algorithms", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-algorithms.git", + "state" : { + "revision" : "87e50f483c54e6efd60e885f7f5aa946cee68023", + "version" : "1.2.1" + } + }, + { + "identity" : "swift-argument-parser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-argument-parser.git", + "state" : { + "revision" : "41982a3656a71c768319979febd796c6fd111d5c", + "version" : "1.5.0" + } + }, + { + "identity" : "swift-atomics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-atomics.git", + "state" : { + "revision" : "cd142fd2f64be2100422d658e7411e39489da985", + "version" : "1.2.0" + } + }, + { + "identity" : "swift-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-collections.git", + "state" : { + "revision" : "671108c96644956dddcd89dd59c203dcdb36cec7", + "version" : "1.1.4" + } + }, + { + "identity" : "swift-http-structured-headers", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-http-structured-headers.git", + "state" : { + "revision" : "8e769facea6b7d46ea60e5e93635a384fd573480", + "version" : "1.2.1" + } + }, + { + "identity" : "swift-http-types", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-http-types.git", + "state" : { + "revision" : "a0a57e949a8903563aba4615869310c0ebf14c03", + "version" : "1.4.0" + } + }, + { + "identity" : "swift-nio", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio.git", + "state" : { + "revision" : "c51907a839e63ebf0ba2076bba73dd96436bd1b9", + "version" : "2.81.0" + } + }, + { + "identity" : "swift-nio-extras", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-extras.git", + "state" : { + "revision" : "00f3f72d2f9942d0e2dc96057ab50a37ced150d4", + "version" : "1.25.0" + } + }, + { + "identity" : "swift-nio-http2", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-http2.git", + "state" : { + "revision" : "170f4ca06b6a9c57b811293cebcb96e81b661310", + "version" : "1.35.0" + } + }, + { + "identity" : "swift-nio-ssl", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-ssl.git", + "state" : { + "revision" : "0cc3528ff48129d64ab9cab0b1cd621634edfc6b", + "version" : "2.29.3" + } + }, + { + "identity" : "swift-nio-transport-services", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-transport-services.git", + "state" : { + "revision" : "3c394067c08d1225ba8442e9cffb520ded417b64", + "version" : "1.23.1" + } + }, + { + "identity" : "swift-numerics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-numerics.git", + "state" : { + "revision" : "e0ec0f5f3af6f3e4d5e7a19d2af26b481acb6ba8", + "version" : "1.0.3" + } + }, + { + "identity" : "swift-protobuf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-protobuf.git", + "state" : { + "revision" : "d72aed98f8253ec1aa9ea1141e28150f408cf17f", + "version" : "1.29.0" + } + }, + { + "identity" : "swift-system", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-system.git", + "state" : { + "revision" : "a34201439c74b53f0fd71ef11741af7e7caf01e1", + "version" : "1.4.2" + } + } + ], + "version" : 3 +} diff --git a/ShimmerBLEGrpc/Package.swift b/ShimmerBLEGrpc/Package.swift new file mode 100644 index 0000000..daa71a5 --- /dev/null +++ b/ShimmerBLEGrpc/Package.swift @@ -0,0 +1,43 @@ +// swift-tools-version:6.0 +/* + * Copyright 2024, gRPC Authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import PackageDescription + +let package = Package( + name: "hello-world", + platforms: [.macOS("15.0")], + dependencies: [ + .package(url: "https://github.com/grpc/grpc-swift.git", from: "2.0.0"), + .package(url: "https://github.com/grpc/grpc-swift-protobuf.git", from: "1.0.0"), + .package(url: "https://github.com/grpc/grpc-swift-nio-transport.git", from: "1.0.0"), + .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.5.0"), + ], + targets: [ + .executableTarget( + name: "hello-world", + dependencies: [ + .product(name: "GRPCCore", package: "grpc-swift"), + .product(name: "GRPCNIOTransportHTTP2", package: "grpc-swift-nio-transport"), + .product(name: "GRPCProtobuf", package: "grpc-swift-protobuf"), + .product(name: "ArgumentParser", package: "swift-argument-parser"), + ], + plugins: [ + .plugin(name: "GRPCProtobufGenerator", package: "grpc-swift-protobuf") + ] + ) + ] +) diff --git a/ShimmerBLEGrpc/Readme.md b/ShimmerBLEGrpc/Readme.md new file mode 100644 index 0000000..28e61a7 --- /dev/null +++ b/ShimmerBLEGrpc/Readme.md @@ -0,0 +1,6 @@ +To run the BLE gRPC server, set the active scheme at the top-middle of Xcode to ShimmerBLEGrpc, target My Mac +Then, select the Start button at the top-left of Xcode to start the app +Then, open the Shimmer-Java-Android-API ShimmerGRPC.java class from: https://github.com/ShimmerEngineering/Shimmer-Java-Android-API/blob/master/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java +Set the name of the device you want to connect to, in Line 101 of the class. This is e.g. "Shimmer3-XXXX". +Note that this is not the Bluetooth Mac address, as MacOS BLE is limited to using Bluetooth device names. +Then, run ShimmerGRPC.java diff --git a/ShimmerBLEGrpc/ShimmerBLEGrpc.entitlements b/ShimmerBLEGrpc/ShimmerBLEGrpc.entitlements new file mode 100644 index 0000000..8cc185a --- /dev/null +++ b/ShimmerBLEGrpc/ShimmerBLEGrpc.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.cs.disable-library-validation + + + diff --git a/ShimmerBLEGrpc/ShimmerBLEGrpc.xcodeproj/project.pbxproj b/ShimmerBLEGrpc/ShimmerBLEGrpc.xcodeproj/project.pbxproj new file mode 100644 index 0000000..cac8bbe --- /dev/null +++ b/ShimmerBLEGrpc/ShimmerBLEGrpc.xcodeproj/project.pbxproj @@ -0,0 +1,473 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXBuildFile section */ + 45345ACA2DA62FA100EA7B41 /* ShimmerBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 45345AC92DA62FA100EA7B41 /* ShimmerBluetooth.framework */; }; + 45345ACB2DA62FA100EA7B41 /* ShimmerBluetooth.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 45345AC92DA62FA100EA7B41 /* ShimmerBluetooth.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 45345ACF2DA6361500EA7B41 /* SwiftProtobuf in Frameworks */ = {isa = PBXBuildFile; productRef = 45345ACE2DA6361500EA7B41 /* SwiftProtobuf */; }; + 45345AD12DA6361500EA7B41 /* SwiftProtobufPluginLibrary in Frameworks */ = {isa = PBXBuildFile; productRef = 45345AD02DA6361500EA7B41 /* SwiftProtobufPluginLibrary */; }; + 45345AEA2DA6399900EA7B41 /* GRPCCodeGen in Frameworks */ = {isa = PBXBuildFile; productRef = 45345AE92DA6399900EA7B41 /* GRPCCodeGen */; }; + 45345AEC2DA6399900EA7B41 /* GRPCCore in Frameworks */ = {isa = PBXBuildFile; productRef = 45345AEB2DA6399900EA7B41 /* GRPCCore */; }; + 45345AEE2DA6399900EA7B41 /* GRPCInProcessTransport in Frameworks */ = {isa = PBXBuildFile; productRef = 45345AED2DA6399900EA7B41 /* GRPCInProcessTransport */; }; + 45345AF12DA639C300EA7B41 /* GRPCProtobuf in Frameworks */ = {isa = PBXBuildFile; productRef = 45345AF02DA639C300EA7B41 /* GRPCProtobuf */; }; + 45345AF42DA639F300EA7B41 /* GRPCNIOTransportHTTP2 in Frameworks */ = {isa = PBXBuildFile; productRef = 45345AF32DA639F300EA7B41 /* GRPCNIOTransportHTTP2 */; }; + 45345AF62DA639F300EA7B41 /* GRPCNIOTransportHTTP2Posix in Frameworks */ = {isa = PBXBuildFile; productRef = 45345AF52DA639F300EA7B41 /* GRPCNIOTransportHTTP2Posix */; }; + 45345AF82DA639F300EA7B41 /* GRPCNIOTransportHTTP2TransportServices in Frameworks */ = {isa = PBXBuildFile; productRef = 45345AF72DA639F300EA7B41 /* GRPCNIOTransportHTTP2TransportServices */; }; + 45345AFB2DA63A1100EA7B41 /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = 45345AFA2DA63A1100EA7B41 /* ArgumentParser */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 45345ACC2DA62FA100EA7B41 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 45345ACB2DA62FA100EA7B41 /* ShimmerBluetooth.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + 456851932DA395630047A883 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 45345AB62DA4F12500EA7B41 /* Readme.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Readme.md; sourceTree = ""; }; + 45345AC22DA62CD700EA7B41 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; + 45345AC92DA62FA100EA7B41 /* ShimmerBluetooth.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = ShimmerBluetooth.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 456851952DA395630047A883 /* ShimmerBLEGrpc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ShimmerBLEGrpc; sourceTree = BUILT_PRODUCTS_DIR; }; + 45A656212DBB4F2E001F8C55 /* ShimmerBLEGrpc.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShimmerBLEGrpc.entitlements; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 45345AAF2DA4F0EF00EA7B41 /* Sources */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = Sources; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + 456851922DA395630047A883 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 45345ACA2DA62FA100EA7B41 /* ShimmerBluetooth.framework in Frameworks */, + 45345AF12DA639C300EA7B41 /* GRPCProtobuf in Frameworks */, + 45345AFB2DA63A1100EA7B41 /* ArgumentParser in Frameworks */, + 45345AEA2DA6399900EA7B41 /* GRPCCodeGen in Frameworks */, + 45345AD12DA6361500EA7B41 /* SwiftProtobufPluginLibrary in Frameworks */, + 45345AEC2DA6399900EA7B41 /* GRPCCore in Frameworks */, + 45345AF62DA639F300EA7B41 /* GRPCNIOTransportHTTP2Posix in Frameworks */, + 45345ACF2DA6361500EA7B41 /* SwiftProtobuf in Frameworks */, + 45345AF42DA639F300EA7B41 /* GRPCNIOTransportHTTP2 in Frameworks */, + 45345AF82DA639F300EA7B41 /* GRPCNIOTransportHTTP2TransportServices in Frameworks */, + 45345AEE2DA6399900EA7B41 /* GRPCInProcessTransport in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 45345AC82DA62FA100EA7B41 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 45345AC92DA62FA100EA7B41 /* ShimmerBluetooth.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 4568518C2DA395630047A883 = { + isa = PBXGroup; + children = ( + 45A656212DBB4F2E001F8C55 /* ShimmerBLEGrpc.entitlements */, + 45345AC22DA62CD700EA7B41 /* Package.swift */, + 45345AB62DA4F12500EA7B41 /* Readme.md */, + 45345AAF2DA4F0EF00EA7B41 /* Sources */, + 45345AC82DA62FA100EA7B41 /* Frameworks */, + 456851962DA395630047A883 /* Products */, + ); + sourceTree = ""; + }; + 456851962DA395630047A883 /* Products */ = { + isa = PBXGroup; + children = ( + 456851952DA395630047A883 /* ShimmerBLEGrpc */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 456851942DA395630047A883 /* ShimmerBLEGrpc */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4568519C2DA395630047A883 /* Build configuration list for PBXNativeTarget "ShimmerBLEGrpc" */; + buildPhases = ( + 456851912DA395630047A883 /* Sources */, + 456851922DA395630047A883 /* Frameworks */, + 456851932DA395630047A883 /* CopyFiles */, + 45345ACC2DA62FA100EA7B41 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 45345AAF2DA4F0EF00EA7B41 /* Sources */, + ); + name = ShimmerBLEGrpc; + packageProductDependencies = ( + 45345ACE2DA6361500EA7B41 /* SwiftProtobuf */, + 45345AD02DA6361500EA7B41 /* SwiftProtobufPluginLibrary */, + 45345AE92DA6399900EA7B41 /* GRPCCodeGen */, + 45345AEB2DA6399900EA7B41 /* GRPCCore */, + 45345AED2DA6399900EA7B41 /* GRPCInProcessTransport */, + 45345AF02DA639C300EA7B41 /* GRPCProtobuf */, + 45345AF32DA639F300EA7B41 /* GRPCNIOTransportHTTP2 */, + 45345AF52DA639F300EA7B41 /* GRPCNIOTransportHTTP2Posix */, + 45345AF72DA639F300EA7B41 /* GRPCNIOTransportHTTP2TransportServices */, + 45345AFA2DA63A1100EA7B41 /* ArgumentParser */, + ); + productName = ShimmerBLEGrpc; + productReference = 456851952DA395630047A883 /* ShimmerBLEGrpc */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4568518D2DA395630047A883 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1610; + LastUpgradeCheck = 1610; + TargetAttributes = { + 456851942DA395630047A883 = { + CreatedOnToolsVersion = 16.1; + }; + }; + }; + buildConfigurationList = 456851902DA395630047A883 /* Build configuration list for PBXProject "ShimmerBLEGrpc" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 4568518C2DA395630047A883; + minimizedProjectReferenceProxies = 1; + packageReferences = ( + 45345ACD2DA6361500EA7B41 /* XCRemoteSwiftPackageReference "swift-protobuf" */, + 45345AE82DA6399900EA7B41 /* XCRemoteSwiftPackageReference "grpc-swift" */, + 45345AEF2DA639C300EA7B41 /* XCRemoteSwiftPackageReference "grpc-swift-protobuf" */, + 45345AF22DA639F300EA7B41 /* XCRemoteSwiftPackageReference "grpc-swift-nio-transport" */, + 45345AF92DA63A1100EA7B41 /* XCRemoteSwiftPackageReference "swift-argument-parser" */, + ); + preferredProjectObjectVersion = 77; + productRefGroup = 456851962DA395630047A883 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 456851942DA395630047A883 /* ShimmerBLEGrpc */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 456851912DA395630047A883 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 4568519A2DA395630047A883 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 15.1; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 4568519B2DA395630047A883 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 15.1; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + }; + name = Release; + }; + 4568519D2DA395630047A883 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = ShimmerBLEGrpc.entitlements; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=macosx*]" = ""; + ENABLE_HARDENED_RUNTIME = YES; + "LD_RUNPATH_SEARCH_PATHS[arch=*]" = "@executable_path"; + PRODUCT_BUNDLE_IDENTIFIER = com.shimmersensing.ShimmerBLEGrpc; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 4568519E2DA395630047A883 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = ShimmerBLEGrpc.entitlements; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=macosx*]" = ""; + ENABLE_HARDENED_RUNTIME = YES; + "LD_RUNPATH_SEARCH_PATHS[arch=*]" = "@executable_path"; + PRODUCT_BUNDLE_IDENTIFIER = com.shimmersensing.ShimmerBLEGrpc; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 456851902DA395630047A883 /* Build configuration list for PBXProject "ShimmerBLEGrpc" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4568519A2DA395630047A883 /* Debug */, + 4568519B2DA395630047A883 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4568519C2DA395630047A883 /* Build configuration list for PBXNativeTarget "ShimmerBLEGrpc" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4568519D2DA395630047A883 /* Debug */, + 4568519E2DA395630047A883 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 45345ACD2DA6361500EA7B41 /* XCRemoteSwiftPackageReference "swift-protobuf" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/apple/swift-protobuf.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.29.0; + }; + }; + 45345AE82DA6399900EA7B41 /* XCRemoteSwiftPackageReference "grpc-swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/grpc/grpc-swift.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.1.2; + }; + }; + 45345AEF2DA639C300EA7B41 /* XCRemoteSwiftPackageReference "grpc-swift-protobuf" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/grpc/grpc-swift-protobuf.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.1.0; + }; + }; + 45345AF22DA639F300EA7B41 /* XCRemoteSwiftPackageReference "grpc-swift-nio-transport" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/grpc/grpc-swift-nio-transport.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.0.3; + }; + }; + 45345AF92DA63A1100EA7B41 /* XCRemoteSwiftPackageReference "swift-argument-parser" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/apple/swift-argument-parser.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.5.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 45345ACE2DA6361500EA7B41 /* SwiftProtobuf */ = { + isa = XCSwiftPackageProductDependency; + package = 45345ACD2DA6361500EA7B41 /* XCRemoteSwiftPackageReference "swift-protobuf" */; + productName = SwiftProtobuf; + }; + 45345AD02DA6361500EA7B41 /* SwiftProtobufPluginLibrary */ = { + isa = XCSwiftPackageProductDependency; + package = 45345ACD2DA6361500EA7B41 /* XCRemoteSwiftPackageReference "swift-protobuf" */; + productName = SwiftProtobufPluginLibrary; + }; + 45345AE92DA6399900EA7B41 /* GRPCCodeGen */ = { + isa = XCSwiftPackageProductDependency; + package = 45345AE82DA6399900EA7B41 /* XCRemoteSwiftPackageReference "grpc-swift" */; + productName = GRPCCodeGen; + }; + 45345AEB2DA6399900EA7B41 /* GRPCCore */ = { + isa = XCSwiftPackageProductDependency; + package = 45345AE82DA6399900EA7B41 /* XCRemoteSwiftPackageReference "grpc-swift" */; + productName = GRPCCore; + }; + 45345AED2DA6399900EA7B41 /* GRPCInProcessTransport */ = { + isa = XCSwiftPackageProductDependency; + package = 45345AE82DA6399900EA7B41 /* XCRemoteSwiftPackageReference "grpc-swift" */; + productName = GRPCInProcessTransport; + }; + 45345AF02DA639C300EA7B41 /* GRPCProtobuf */ = { + isa = XCSwiftPackageProductDependency; + package = 45345AEF2DA639C300EA7B41 /* XCRemoteSwiftPackageReference "grpc-swift-protobuf" */; + productName = GRPCProtobuf; + }; + 45345AF32DA639F300EA7B41 /* GRPCNIOTransportHTTP2 */ = { + isa = XCSwiftPackageProductDependency; + package = 45345AF22DA639F300EA7B41 /* XCRemoteSwiftPackageReference "grpc-swift-nio-transport" */; + productName = GRPCNIOTransportHTTP2; + }; + 45345AF52DA639F300EA7B41 /* GRPCNIOTransportHTTP2Posix */ = { + isa = XCSwiftPackageProductDependency; + package = 45345AF22DA639F300EA7B41 /* XCRemoteSwiftPackageReference "grpc-swift-nio-transport" */; + productName = GRPCNIOTransportHTTP2Posix; + }; + 45345AF72DA639F300EA7B41 /* GRPCNIOTransportHTTP2TransportServices */ = { + isa = XCSwiftPackageProductDependency; + package = 45345AF22DA639F300EA7B41 /* XCRemoteSwiftPackageReference "grpc-swift-nio-transport" */; + productName = GRPCNIOTransportHTTP2TransportServices; + }; + 45345AFA2DA63A1100EA7B41 /* ArgumentParser */ = { + isa = XCSwiftPackageProductDependency; + package = 45345AF92DA63A1100EA7B41 /* XCRemoteSwiftPackageReference "swift-argument-parser" */; + productName = ArgumentParser; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 4568518D2DA395630047A883 /* Project object */; +} diff --git a/ShimmerBLEGrpc/ShimmerBLEGrpc.xcodeproj/xcshareddata/xcschemes/ShimmerBLEGrpc.xcscheme b/ShimmerBLEGrpc/ShimmerBLEGrpc.xcodeproj/xcshareddata/xcschemes/ShimmerBLEGrpc.xcscheme new file mode 100644 index 0000000..5893bc3 --- /dev/null +++ b/ShimmerBLEGrpc/ShimmerBLEGrpc.xcodeproj/xcshareddata/xcschemes/ShimmerBLEGrpc.xcscheme @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ShimmerBLEGrpc/Sources/Protos/ShimmerBLEGrpcAndPacketByteArray.grpc.swift b/ShimmerBLEGrpc/Sources/Protos/ShimmerBLEGrpcAndPacketByteArray.grpc.swift new file mode 100644 index 0000000..a0dcbff --- /dev/null +++ b/ShimmerBLEGrpc/Sources/Protos/ShimmerBLEGrpcAndPacketByteArray.grpc.swift @@ -0,0 +1,1565 @@ +///using +///protoc-3.13.0-win64 +///protoc-gen-grpc-java-1.32.1-windows-x86_64.exe +///.nuget\packages\grpc.tools\2.34.0\tools\windows_x64\grpc_csharp_plugin.exe + +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the gRPC Swift generator plugin for the protocol buffer compiler. +// Source: ShimmerBLEGrpcAndPacketByteArray.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/grpc/grpc-swift + +import GRPCCore +import GRPCProtobuf + +// MARK: - shimmerBLEGRPC.ShimmerBLEByteServer + +/// Namespace containing generated types for the "shimmerBLEGRPC.ShimmerBLEByteServer" service. +internal enum ShimmerBLEGRPC_ShimmerBLEByteServer { + /// Service descriptor for the "shimmerBLEGRPC.ShimmerBLEByteServer" service. + internal static let descriptor = GRPCCore.ServiceDescriptor(fullyQualifiedService: "shimmerBLEGRPC.ShimmerBLEByteServer") + /// Namespace for method metadata. + internal enum Method { + /// Namespace for "GetDataStream" metadata. + internal enum GetDataStream { + /// Request type for "GetDataStream". + internal typealias Input = ShimmerBLEGRPC_StreamRequest + /// Response type for "GetDataStream". + internal typealias Output = ShimmerBLEGRPC_ObjectClusterByteArray + /// Descriptor for "GetDataStream". + internal static let descriptor = GRPCCore.MethodDescriptor( + service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "shimmerBLEGRPC.ShimmerBLEByteServer"), + method: "GetDataStream" + ) + } + /// Namespace for "GetTestDataStream" metadata. + internal enum GetTestDataStream { + /// Request type for "GetTestDataStream". + internal typealias Input = ShimmerBLEGRPC_StreamRequest + /// Response type for "GetTestDataStream". + internal typealias Output = ShimmerBLEGRPC_ObjectClusterByteArray + /// Descriptor for "GetTestDataStream". + internal static let descriptor = GRPCCore.MethodDescriptor( + service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "shimmerBLEGRPC.ShimmerBLEByteServer"), + method: "GetTestDataStream" + ) + } + /// Namespace for "SendDataStream" metadata. + internal enum SendDataStream { + /// Request type for "SendDataStream". + internal typealias Input = ShimmerBLEGRPC_ObjectClusterByteArray + /// Response type for "SendDataStream". + internal typealias Output = ShimmerBLEGRPC_Reply + /// Descriptor for "SendDataStream". + internal static let descriptor = GRPCCore.MethodDescriptor( + service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "shimmerBLEGRPC.ShimmerBLEByteServer"), + method: "SendDataStream" + ) + } + /// Namespace for "ConnectShimmer" metadata. + internal enum ConnectShimmer { + /// Request type for "ConnectShimmer". + internal typealias Input = ShimmerBLEGRPC_Request + /// Response type for "ConnectShimmer". + internal typealias Output = ShimmerBLEGRPC_StateStatus + /// Descriptor for "ConnectShimmer". + internal static let descriptor = GRPCCore.MethodDescriptor( + service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "shimmerBLEGRPC.ShimmerBLEByteServer"), + method: "ConnectShimmer" + ) + } + /// Namespace for "DisconnectShimmer" metadata. + internal enum DisconnectShimmer { + /// Request type for "DisconnectShimmer". + internal typealias Input = ShimmerBLEGRPC_Request + /// Response type for "DisconnectShimmer". + internal typealias Output = ShimmerBLEGRPC_Reply + /// Descriptor for "DisconnectShimmer". + internal static let descriptor = GRPCCore.MethodDescriptor( + service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "shimmerBLEGRPC.ShimmerBLEByteServer"), + method: "DisconnectShimmer" + ) + } + /// Namespace for "WriteBytesShimmer" metadata. + internal enum WriteBytesShimmer { + /// Request type for "WriteBytesShimmer". + internal typealias Input = ShimmerBLEGRPC_WriteBytes + /// Response type for "WriteBytesShimmer". + internal typealias Output = ShimmerBLEGRPC_Reply + /// Descriptor for "WriteBytesShimmer". + internal static let descriptor = GRPCCore.MethodDescriptor( + service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "shimmerBLEGRPC.ShimmerBLEByteServer"), + method: "WriteBytesShimmer" + ) + } + /// Namespace for "SayHello" metadata. + internal enum SayHello { + /// Request type for "SayHello". + internal typealias Input = ShimmerBLEGRPC_Request + /// Response type for "SayHello". + internal typealias Output = ShimmerBLEGRPC_Reply + /// Descriptor for "SayHello". + internal static let descriptor = GRPCCore.MethodDescriptor( + service: GRPCCore.ServiceDescriptor(fullyQualifiedService: "shimmerBLEGRPC.ShimmerBLEByteServer"), + method: "SayHello" + ) + } + /// Descriptors for all methods in the "shimmerBLEGRPC.ShimmerBLEByteServer" service. + internal static let descriptors: [GRPCCore.MethodDescriptor] = [ + GetDataStream.descriptor, + GetTestDataStream.descriptor, + SendDataStream.descriptor, + ConnectShimmer.descriptor, + DisconnectShimmer.descriptor, + WriteBytesShimmer.descriptor, + SayHello.descriptor + ] + } +} + +extension GRPCCore.ServiceDescriptor { + /// Service descriptor for the "shimmerBLEGRPC.ShimmerBLEByteServer" service. + internal static let shimmerBlegrpc_ShimmerBLEByteServer = GRPCCore.ServiceDescriptor(fullyQualifiedService: "shimmerBLEGRPC.ShimmerBLEByteServer") +} + +// MARK: shimmerBLEGRPC.ShimmerBLEByteServer (server) + +extension ShimmerBLEGRPC_ShimmerBLEByteServer { + /// Streaming variant of the service protocol for the "shimmerBLEGRPC.ShimmerBLEByteServer" service. + /// + /// This protocol is the lowest-level of the service protocols generated for this service + /// giving you the most flexibility over the implementation of your service. This comes at + /// the cost of more verbose and less strict APIs. Each RPC requires you to implement it in + /// terms of a request stream and response stream. Where only a single request or response + /// message is expected, you are responsible for enforcing this invariant is maintained. + /// + /// Where possible, prefer using the stricter, less-verbose ``ServiceProtocol`` + /// or ``SimpleServiceProtocol`` instead. + /// + /// > Source IDL Documentation: + /// > + /// > The greeter service definition. + internal protocol StreamingServiceProtocol: GRPCCore.RegistrableRPCService { + /// Handle the "GetDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient asking for data + /// + /// - Parameters: + /// - request: A streaming request of `ShimmerBLEGRPC_StreamRequest` messages. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A streaming response of `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + func getDataStream( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse + + /// Handle the "GetTestDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient asking for data + /// + /// - Parameters: + /// - request: A streaming request of `ShimmerBLEGRPC_StreamRequest` messages. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A streaming response of `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + func getTestDataStream( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse + + /// Handle the "SendDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient sending data + /// + /// - Parameters: + /// - request: A streaming request of `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A streaming response of `ShimmerBLEGRPC_Reply` messages. + func sendDataStream( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse + + /// Handle the "ConnectShimmer" method. + /// + /// - Parameters: + /// - request: A streaming request of `ShimmerBLEGRPC_Request` messages. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A streaming response of `ShimmerBLEGRPC_StateStatus` messages. + func connectShimmer( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse + + /// Handle the "DisconnectShimmer" method. + /// + /// - Parameters: + /// - request: A streaming request of `ShimmerBLEGRPC_Request` messages. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A streaming response of `ShimmerBLEGRPC_Reply` messages. + func disconnectShimmer( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse + + /// Handle the "WriteBytesShimmer" method. + /// + /// - Parameters: + /// - request: A streaming request of `ShimmerBLEGRPC_WriteBytes` messages. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A streaming response of `ShimmerBLEGRPC_Reply` messages. + func writeBytesShimmer( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse + + /// Handle the "SayHello" method. + /// + /// - Parameters: + /// - request: A streaming request of `ShimmerBLEGRPC_Request` messages. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A streaming response of `ShimmerBLEGRPC_Reply` messages. + func sayHello( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse + } + + /// Service protocol for the "shimmerBLEGRPC.ShimmerBLEByteServer" service. + /// + /// This protocol is higher level than ``StreamingServiceProtocol`` but lower level than + /// the ``SimpleServiceProtocol``, it provides access to request and response metadata and + /// trailing response metadata. If you don't need these then consider using + /// the ``SimpleServiceProtocol``. If you need fine grained control over your RPCs then + /// use ``StreamingServiceProtocol``. + /// + /// > Source IDL Documentation: + /// > + /// > The greeter service definition. + internal protocol ServiceProtocol: ShimmerBLEGRPC_ShimmerBLEByteServer.StreamingServiceProtocol { + /// Handle the "GetDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient asking for data + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_StreamRequest` message. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A streaming response of `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + func getDataStream( + request: GRPCCore.ServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse + + /// Handle the "GetTestDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient asking for data + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_StreamRequest` message. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A streaming response of `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + func getTestDataStream( + request: GRPCCore.ServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse + + /// Handle the "SendDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient sending data + /// + /// - Parameters: + /// - request: A streaming request of `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A response containing a single `ShimmerBLEGRPC_Reply` message. + func sendDataStream( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.ServerResponse + + /// Handle the "ConnectShimmer" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_Request` message. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A streaming response of `ShimmerBLEGRPC_StateStatus` messages. + func connectShimmer( + request: GRPCCore.ServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse + + /// Handle the "DisconnectShimmer" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_Request` message. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A response containing a single `ShimmerBLEGRPC_Reply` message. + func disconnectShimmer( + request: GRPCCore.ServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.ServerResponse + + /// Handle the "WriteBytesShimmer" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_WriteBytes` message. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A response containing a single `ShimmerBLEGRPC_Reply` message. + func writeBytesShimmer( + request: GRPCCore.ServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.ServerResponse + + /// Handle the "SayHello" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_Request` message. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A response containing a single `ShimmerBLEGRPC_Reply` message. + func sayHello( + request: GRPCCore.ServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.ServerResponse + } + + /// Simple service protocol for the "shimmerBLEGRPC.ShimmerBLEByteServer" service. + /// + /// This is the highest level protocol for the service. The API is the easiest to use but + /// doesn't provide access to request or response metadata. If you need access to these + /// then use ``ServiceProtocol`` instead. + /// + /// > Source IDL Documentation: + /// > + /// > The greeter service definition. + internal protocol SimpleServiceProtocol: ShimmerBLEGRPC_ShimmerBLEByteServer.ServiceProtocol { + /// Handle the "GetDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient asking for data + /// + /// - Parameters: + /// - request: A `ShimmerBLEGRPC_StreamRequest` message. + /// - response: A response stream of `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + func getDataStream( + request: ShimmerBLEGRPC_StreamRequest, + response: GRPCCore.RPCWriter, + context: GRPCCore.ServerContext + ) async throws + + /// Handle the "GetTestDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient asking for data + /// + /// - Parameters: + /// - request: A `ShimmerBLEGRPC_StreamRequest` message. + /// - response: A response stream of `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + func getTestDataStream( + request: ShimmerBLEGRPC_StreamRequest, + response: GRPCCore.RPCWriter, + context: GRPCCore.ServerContext + ) async throws + + /// Handle the "SendDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient sending data + /// + /// - Parameters: + /// - request: A stream of `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A `ShimmerBLEGRPC_Reply` to respond with. + func sendDataStream( + request: GRPCCore.RPCAsyncSequence, + context: GRPCCore.ServerContext + ) async throws -> ShimmerBLEGRPC_Reply + + /// Handle the "ConnectShimmer" method. + /// + /// - Parameters: + /// - request: A `ShimmerBLEGRPC_Request` message. + /// - response: A response stream of `ShimmerBLEGRPC_StateStatus` messages. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + func connectShimmer( + request: ShimmerBLEGRPC_Request, + response: GRPCCore.RPCWriter, + context: GRPCCore.ServerContext + ) async throws + + /// Handle the "DisconnectShimmer" method. + /// + /// - Parameters: + /// - request: A `ShimmerBLEGRPC_Request` message. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A `ShimmerBLEGRPC_Reply` to respond with. + func disconnectShimmer( + request: ShimmerBLEGRPC_Request, + context: GRPCCore.ServerContext + ) async throws -> ShimmerBLEGRPC_Reply + + /// Handle the "WriteBytesShimmer" method. + /// + /// - Parameters: + /// - request: A `ShimmerBLEGRPC_WriteBytes` message. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A `ShimmerBLEGRPC_Reply` to respond with. + func writeBytesShimmer( + request: ShimmerBLEGRPC_WriteBytes, + context: GRPCCore.ServerContext + ) async throws -> ShimmerBLEGRPC_Reply + + /// Handle the "SayHello" method. + /// + /// - Parameters: + /// - request: A `ShimmerBLEGRPC_Request` message. + /// - context: Context providing information about the RPC. + /// - Throws: Any error which occurred during the processing of the request. Thrown errors + /// of type `RPCError` are mapped to appropriate statuses. All other errors are converted + /// to an internal error. + /// - Returns: A `ShimmerBLEGRPC_Reply` to respond with. + func sayHello( + request: ShimmerBLEGRPC_Request, + context: GRPCCore.ServerContext + ) async throws -> ShimmerBLEGRPC_Reply + } +} + +// Default implementation of 'registerMethods(with:)'. +extension ShimmerBLEGRPC_ShimmerBLEByteServer.StreamingServiceProtocol { + internal func registerMethods(with router: inout GRPCCore.RPCRouter) where Transport: GRPCCore.ServerTransport { + router.registerHandler( + forMethod: ShimmerBLEGRPC_ShimmerBLEByteServer.Method.GetDataStream.descriptor, + deserializer: GRPCProtobuf.ProtobufDeserializer(), + serializer: GRPCProtobuf.ProtobufSerializer(), + handler: { request, context in + try await self.getDataStream( + request: request, + context: context + ) + } + ) + router.registerHandler( + forMethod: ShimmerBLEGRPC_ShimmerBLEByteServer.Method.GetTestDataStream.descriptor, + deserializer: GRPCProtobuf.ProtobufDeserializer(), + serializer: GRPCProtobuf.ProtobufSerializer(), + handler: { request, context in + try await self.getTestDataStream( + request: request, + context: context + ) + } + ) + router.registerHandler( + forMethod: ShimmerBLEGRPC_ShimmerBLEByteServer.Method.SendDataStream.descriptor, + deserializer: GRPCProtobuf.ProtobufDeserializer(), + serializer: GRPCProtobuf.ProtobufSerializer(), + handler: { request, context in + try await self.sendDataStream( + request: request, + context: context + ) + } + ) + router.registerHandler( + forMethod: ShimmerBLEGRPC_ShimmerBLEByteServer.Method.ConnectShimmer.descriptor, + deserializer: GRPCProtobuf.ProtobufDeserializer(), + serializer: GRPCProtobuf.ProtobufSerializer(), + handler: { request, context in + try await self.connectShimmer( + request: request, + context: context + ) + } + ) + router.registerHandler( + forMethod: ShimmerBLEGRPC_ShimmerBLEByteServer.Method.DisconnectShimmer.descriptor, + deserializer: GRPCProtobuf.ProtobufDeserializer(), + serializer: GRPCProtobuf.ProtobufSerializer(), + handler: { request, context in + try await self.disconnectShimmer( + request: request, + context: context + ) + } + ) + router.registerHandler( + forMethod: ShimmerBLEGRPC_ShimmerBLEByteServer.Method.WriteBytesShimmer.descriptor, + deserializer: GRPCProtobuf.ProtobufDeserializer(), + serializer: GRPCProtobuf.ProtobufSerializer(), + handler: { request, context in + try await self.writeBytesShimmer( + request: request, + context: context + ) + } + ) + router.registerHandler( + forMethod: ShimmerBLEGRPC_ShimmerBLEByteServer.Method.SayHello.descriptor, + deserializer: GRPCProtobuf.ProtobufDeserializer(), + serializer: GRPCProtobuf.ProtobufSerializer(), + handler: { request, context in + try await self.sayHello( + request: request, + context: context + ) + } + ) + } +} + +// Default implementation of streaming methods from 'StreamingServiceProtocol'. +extension ShimmerBLEGRPC_ShimmerBLEByteServer.ServiceProtocol { + internal func getDataStream( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse { + let response = try await self.getDataStream( + request: GRPCCore.ServerRequest(stream: request), + context: context + ) + return response + } + + internal func getTestDataStream( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse { + let response = try await self.getTestDataStream( + request: GRPCCore.ServerRequest(stream: request), + context: context + ) + return response + } + + internal func sendDataStream( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse { + let response = try await self.sendDataStream( + request: request, + context: context + ) + return GRPCCore.StreamingServerResponse(single: response) + } + + internal func connectShimmer( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse { + let response = try await self.connectShimmer( + request: GRPCCore.ServerRequest(stream: request), + context: context + ) + return response + } + + internal func disconnectShimmer( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse { + let response = try await self.disconnectShimmer( + request: GRPCCore.ServerRequest(stream: request), + context: context + ) + return GRPCCore.StreamingServerResponse(single: response) + } + + internal func writeBytesShimmer( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse { + let response = try await self.writeBytesShimmer( + request: GRPCCore.ServerRequest(stream: request), + context: context + ) + return GRPCCore.StreamingServerResponse(single: response) + } + + internal func sayHello( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse { + let response = try await self.sayHello( + request: GRPCCore.ServerRequest(stream: request), + context: context + ) + return GRPCCore.StreamingServerResponse(single: response) + } +} + +// Default implementation of methods from 'ServiceProtocol'. +extension ShimmerBLEGRPC_ShimmerBLEByteServer.SimpleServiceProtocol { + internal func getDataStream( + request: GRPCCore.ServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse { + return GRPCCore.StreamingServerResponse( + metadata: [:], + producer: { writer in + try await self.getDataStream( + request: request.message, + response: writer, + context: context + ) + return [:] + } + ) + } + + internal func getTestDataStream( + request: GRPCCore.ServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse { + return GRPCCore.StreamingServerResponse( + metadata: [:], + producer: { writer in + try await self.getTestDataStream( + request: request.message, + response: writer, + context: context + ) + return [:] + } + ) + } + + internal func sendDataStream( + request: GRPCCore.StreamingServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.ServerResponse { + return GRPCCore.ServerResponse( + message: try await self.sendDataStream( + request: request.messages, + context: context + ), + metadata: [:] + ) + } + + internal func connectShimmer( + request: GRPCCore.ServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.StreamingServerResponse { + return GRPCCore.StreamingServerResponse( + metadata: [:], + producer: { writer in + try await self.connectShimmer( + request: request.message, + response: writer, + context: context + ) + return [:] + } + ) + } + + internal func disconnectShimmer( + request: GRPCCore.ServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.ServerResponse { + return GRPCCore.ServerResponse( + message: try await self.disconnectShimmer( + request: request.message, + context: context + ), + metadata: [:] + ) + } + + internal func writeBytesShimmer( + request: GRPCCore.ServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.ServerResponse { + return GRPCCore.ServerResponse( + message: try await self.writeBytesShimmer( + request: request.message, + context: context + ), + metadata: [:] + ) + } + + internal func sayHello( + request: GRPCCore.ServerRequest, + context: GRPCCore.ServerContext + ) async throws -> GRPCCore.ServerResponse { + return GRPCCore.ServerResponse( + message: try await self.sayHello( + request: request.message, + context: context + ), + metadata: [:] + ) + } +} + +// MARK: shimmerBLEGRPC.ShimmerBLEByteServer (client) + +extension ShimmerBLEGRPC_ShimmerBLEByteServer { + /// Generated client protocol for the "shimmerBLEGRPC.ShimmerBLEByteServer" service. + /// + /// You don't need to implement this protocol directly, use the generated + /// implementation, ``Client``. + /// + /// > Source IDL Documentation: + /// > + /// > The greeter service definition. + internal protocol ClientProtocol: Sendable { + /// Call the "GetDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient asking for data + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_StreamRequest` message. + /// - serializer: A serializer for `ShimmerBLEGRPC_StreamRequest` messages. + /// - deserializer: A deserializer for `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + func getDataStream( + request: GRPCCore.ClientRequest, + serializer: some GRPCCore.MessageSerializer, + deserializer: some GRPCCore.MessageDeserializer, + options: GRPCCore.CallOptions, + onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable + + /// Call the "GetTestDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient asking for data + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_StreamRequest` message. + /// - serializer: A serializer for `ShimmerBLEGRPC_StreamRequest` messages. + /// - deserializer: A deserializer for `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + func getTestDataStream( + request: GRPCCore.ClientRequest, + serializer: some GRPCCore.MessageSerializer, + deserializer: some GRPCCore.MessageDeserializer, + options: GRPCCore.CallOptions, + onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable + + /// Call the "SendDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient sending data + /// + /// - Parameters: + /// - request: A streaming request producing `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + /// - serializer: A serializer for `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + /// - deserializer: A deserializer for `ShimmerBLEGRPC_Reply` messages. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + func sendDataStream( + request: GRPCCore.StreamingClientRequest, + serializer: some GRPCCore.MessageSerializer, + deserializer: some GRPCCore.MessageDeserializer, + options: GRPCCore.CallOptions, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable + + /// Call the "ConnectShimmer" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_Request` message. + /// - serializer: A serializer for `ShimmerBLEGRPC_Request` messages. + /// - deserializer: A deserializer for `ShimmerBLEGRPC_StateStatus` messages. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + func connectShimmer( + request: GRPCCore.ClientRequest, + serializer: some GRPCCore.MessageSerializer, + deserializer: some GRPCCore.MessageDeserializer, + options: GRPCCore.CallOptions, + onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable + + /// Call the "DisconnectShimmer" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_Request` message. + /// - serializer: A serializer for `ShimmerBLEGRPC_Request` messages. + /// - deserializer: A deserializer for `ShimmerBLEGRPC_Reply` messages. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + func disconnectShimmer( + request: GRPCCore.ClientRequest, + serializer: some GRPCCore.MessageSerializer, + deserializer: some GRPCCore.MessageDeserializer, + options: GRPCCore.CallOptions, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable + + /// Call the "WriteBytesShimmer" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_WriteBytes` message. + /// - serializer: A serializer for `ShimmerBLEGRPC_WriteBytes` messages. + /// - deserializer: A deserializer for `ShimmerBLEGRPC_Reply` messages. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + func writeBytesShimmer( + request: GRPCCore.ClientRequest, + serializer: some GRPCCore.MessageSerializer, + deserializer: some GRPCCore.MessageDeserializer, + options: GRPCCore.CallOptions, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable + + /// Call the "SayHello" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_Request` message. + /// - serializer: A serializer for `ShimmerBLEGRPC_Request` messages. + /// - deserializer: A deserializer for `ShimmerBLEGRPC_Reply` messages. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + func sayHello( + request: GRPCCore.ClientRequest, + serializer: some GRPCCore.MessageSerializer, + deserializer: some GRPCCore.MessageDeserializer, + options: GRPCCore.CallOptions, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable + } + + /// Generated client for the "shimmerBLEGRPC.ShimmerBLEByteServer" service. + /// + /// The ``Client`` provides an implementation of ``ClientProtocol`` which wraps + /// a `GRPCCore.GRPCCClient`. The underlying `GRPCClient` provides the long-lived + /// means of communication with the remote peer. + /// + /// > Source IDL Documentation: + /// > + /// > The greeter service definition. + internal struct Client: ClientProtocol where Transport: GRPCCore.ClientTransport { + private let client: GRPCCore.GRPCClient + + /// Creates a new client wrapping the provided `GRPCCore.GRPCClient`. + /// + /// - Parameters: + /// - client: A `GRPCCore.GRPCClient` providing a communication channel to the service. + internal init(wrapping client: GRPCCore.GRPCClient) { + self.client = client + } + + /// Call the "GetDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient asking for data + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_StreamRequest` message. + /// - serializer: A serializer for `ShimmerBLEGRPC_StreamRequest` messages. + /// - deserializer: A deserializer for `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func getDataStream( + request: GRPCCore.ClientRequest, + serializer: some GRPCCore.MessageSerializer, + deserializer: some GRPCCore.MessageDeserializer, + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable { + try await self.client.serverStreaming( + request: request, + descriptor: ShimmerBLEGRPC_ShimmerBLEByteServer.Method.GetDataStream.descriptor, + serializer: serializer, + deserializer: deserializer, + options: options, + onResponse: handleResponse + ) + } + + /// Call the "GetTestDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient asking for data + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_StreamRequest` message. + /// - serializer: A serializer for `ShimmerBLEGRPC_StreamRequest` messages. + /// - deserializer: A deserializer for `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func getTestDataStream( + request: GRPCCore.ClientRequest, + serializer: some GRPCCore.MessageSerializer, + deserializer: some GRPCCore.MessageDeserializer, + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable { + try await self.client.serverStreaming( + request: request, + descriptor: ShimmerBLEGRPC_ShimmerBLEByteServer.Method.GetTestDataStream.descriptor, + serializer: serializer, + deserializer: deserializer, + options: options, + onResponse: handleResponse + ) + } + + /// Call the "SendDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient sending data + /// + /// - Parameters: + /// - request: A streaming request producing `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + /// - serializer: A serializer for `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + /// - deserializer: A deserializer for `ShimmerBLEGRPC_Reply` messages. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func sendDataStream( + request: GRPCCore.StreamingClientRequest, + serializer: some GRPCCore.MessageSerializer, + deserializer: some GRPCCore.MessageDeserializer, + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in + try response.message + } + ) async throws -> Result where Result: Sendable { + try await self.client.clientStreaming( + request: request, + descriptor: ShimmerBLEGRPC_ShimmerBLEByteServer.Method.SendDataStream.descriptor, + serializer: serializer, + deserializer: deserializer, + options: options, + onResponse: handleResponse + ) + } + + /// Call the "ConnectShimmer" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_Request` message. + /// - serializer: A serializer for `ShimmerBLEGRPC_Request` messages. + /// - deserializer: A deserializer for `ShimmerBLEGRPC_StateStatus` messages. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func connectShimmer( + request: GRPCCore.ClientRequest, + serializer: some GRPCCore.MessageSerializer, + deserializer: some GRPCCore.MessageDeserializer, + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable { + try await self.client.serverStreaming( + request: request, + descriptor: ShimmerBLEGRPC_ShimmerBLEByteServer.Method.ConnectShimmer.descriptor, + serializer: serializer, + deserializer: deserializer, + options: options, + onResponse: handleResponse + ) + } + + /// Call the "DisconnectShimmer" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_Request` message. + /// - serializer: A serializer for `ShimmerBLEGRPC_Request` messages. + /// - deserializer: A deserializer for `ShimmerBLEGRPC_Reply` messages. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func disconnectShimmer( + request: GRPCCore.ClientRequest, + serializer: some GRPCCore.MessageSerializer, + deserializer: some GRPCCore.MessageDeserializer, + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in + try response.message + } + ) async throws -> Result where Result: Sendable { + try await self.client.unary( + request: request, + descriptor: ShimmerBLEGRPC_ShimmerBLEByteServer.Method.DisconnectShimmer.descriptor, + serializer: serializer, + deserializer: deserializer, + options: options, + onResponse: handleResponse + ) + } + + /// Call the "WriteBytesShimmer" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_WriteBytes` message. + /// - serializer: A serializer for `ShimmerBLEGRPC_WriteBytes` messages. + /// - deserializer: A deserializer for `ShimmerBLEGRPC_Reply` messages. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func writeBytesShimmer( + request: GRPCCore.ClientRequest, + serializer: some GRPCCore.MessageSerializer, + deserializer: some GRPCCore.MessageDeserializer, + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in + try response.message + } + ) async throws -> Result where Result: Sendable { + try await self.client.unary( + request: request, + descriptor: ShimmerBLEGRPC_ShimmerBLEByteServer.Method.WriteBytesShimmer.descriptor, + serializer: serializer, + deserializer: deserializer, + options: options, + onResponse: handleResponse + ) + } + + /// Call the "SayHello" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_Request` message. + /// - serializer: A serializer for `ShimmerBLEGRPC_Request` messages. + /// - deserializer: A deserializer for `ShimmerBLEGRPC_Reply` messages. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func sayHello( + request: GRPCCore.ClientRequest, + serializer: some GRPCCore.MessageSerializer, + deserializer: some GRPCCore.MessageDeserializer, + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in + try response.message + } + ) async throws -> Result where Result: Sendable { + try await self.client.unary( + request: request, + descriptor: ShimmerBLEGRPC_ShimmerBLEByteServer.Method.SayHello.descriptor, + serializer: serializer, + deserializer: deserializer, + options: options, + onResponse: handleResponse + ) + } + } +} + +// Helpers providing default arguments to 'ClientProtocol' methods. +extension ShimmerBLEGRPC_ShimmerBLEByteServer.ClientProtocol { + /// Call the "GetDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient asking for data + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_StreamRequest` message. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func getDataStream( + request: GRPCCore.ClientRequest, + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable { + try await self.getDataStream( + request: request, + serializer: GRPCProtobuf.ProtobufSerializer(), + deserializer: GRPCProtobuf.ProtobufDeserializer(), + options: options, + onResponse: handleResponse + ) + } + + /// Call the "GetTestDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient asking for data + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_StreamRequest` message. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func getTestDataStream( + request: GRPCCore.ClientRequest, + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable { + try await self.getTestDataStream( + request: request, + serializer: GRPCProtobuf.ProtobufSerializer(), + deserializer: GRPCProtobuf.ProtobufDeserializer(), + options: options, + onResponse: handleResponse + ) + } + + /// Call the "SendDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient sending data + /// + /// - Parameters: + /// - request: A streaming request producing `ShimmerBLEGRPC_ObjectClusterByteArray` messages. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func sendDataStream( + request: GRPCCore.StreamingClientRequest, + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in + try response.message + } + ) async throws -> Result where Result: Sendable { + try await self.sendDataStream( + request: request, + serializer: GRPCProtobuf.ProtobufSerializer(), + deserializer: GRPCProtobuf.ProtobufDeserializer(), + options: options, + onResponse: handleResponse + ) + } + + /// Call the "ConnectShimmer" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_Request` message. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func connectShimmer( + request: GRPCCore.ClientRequest, + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable { + try await self.connectShimmer( + request: request, + serializer: GRPCProtobuf.ProtobufSerializer(), + deserializer: GRPCProtobuf.ProtobufDeserializer(), + options: options, + onResponse: handleResponse + ) + } + + /// Call the "DisconnectShimmer" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_Request` message. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func disconnectShimmer( + request: GRPCCore.ClientRequest, + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in + try response.message + } + ) async throws -> Result where Result: Sendable { + try await self.disconnectShimmer( + request: request, + serializer: GRPCProtobuf.ProtobufSerializer(), + deserializer: GRPCProtobuf.ProtobufDeserializer(), + options: options, + onResponse: handleResponse + ) + } + + /// Call the "WriteBytesShimmer" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_WriteBytes` message. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func writeBytesShimmer( + request: GRPCCore.ClientRequest, + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in + try response.message + } + ) async throws -> Result where Result: Sendable { + try await self.writeBytesShimmer( + request: request, + serializer: GRPCProtobuf.ProtobufSerializer(), + deserializer: GRPCProtobuf.ProtobufDeserializer(), + options: options, + onResponse: handleResponse + ) + } + + /// Call the "SayHello" method. + /// + /// - Parameters: + /// - request: A request containing a single `ShimmerBLEGRPC_Request` message. + /// - options: Options to apply to this RPC. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func sayHello( + request: GRPCCore.ClientRequest, + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in + try response.message + } + ) async throws -> Result where Result: Sendable { + try await self.sayHello( + request: request, + serializer: GRPCProtobuf.ProtobufSerializer(), + deserializer: GRPCProtobuf.ProtobufDeserializer(), + options: options, + onResponse: handleResponse + ) + } +} + +// Helpers providing sugared APIs for 'ClientProtocol' methods. +extension ShimmerBLEGRPC_ShimmerBLEByteServer.ClientProtocol { + /// Call the "GetDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient asking for data + /// + /// - Parameters: + /// - message: request message to send. + /// - metadata: Additional metadata to send, defaults to empty. + /// - options: Options to apply to this RPC, defaults to `.defaults`. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func getDataStream( + _ message: ShimmerBLEGRPC_StreamRequest, + metadata: GRPCCore.Metadata = [:], + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable { + let request = GRPCCore.ClientRequest( + message: message, + metadata: metadata + ) + return try await self.getDataStream( + request: request, + options: options, + onResponse: handleResponse + ) + } + + /// Call the "GetTestDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient asking for data + /// + /// - Parameters: + /// - message: request message to send. + /// - metadata: Additional metadata to send, defaults to empty. + /// - options: Options to apply to this RPC, defaults to `.defaults`. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func getTestDataStream( + _ message: ShimmerBLEGRPC_StreamRequest, + metadata: GRPCCore.Metadata = [:], + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable { + let request = GRPCCore.ClientRequest( + message: message, + metadata: metadata + ) + return try await self.getTestDataStream( + request: request, + options: options, + onResponse: handleResponse + ) + } + + /// Call the "SendDataStream" method. + /// + /// > Source IDL Documentation: + /// > + /// > lient sending data + /// + /// - Parameters: + /// - metadata: Additional metadata to send, defaults to empty. + /// - options: Options to apply to this RPC, defaults to `.defaults`. + /// - producer: A closure producing request messages to send to the server. The request + /// stream is closed when the closure returns. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func sendDataStream( + metadata: GRPCCore.Metadata = [:], + options: GRPCCore.CallOptions = .defaults, + requestProducer producer: @Sendable @escaping (GRPCCore.RPCWriter) async throws -> Void, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in + try response.message + } + ) async throws -> Result where Result: Sendable { + let request = GRPCCore.StreamingClientRequest( + metadata: metadata, + producer: producer + ) + return try await self.sendDataStream( + request: request, + options: options, + onResponse: handleResponse + ) + } + + /// Call the "ConnectShimmer" method. + /// + /// - Parameters: + /// - message: request message to send. + /// - metadata: Additional metadata to send, defaults to empty. + /// - options: Options to apply to this RPC, defaults to `.defaults`. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func connectShimmer( + _ message: ShimmerBLEGRPC_Request, + metadata: GRPCCore.Metadata = [:], + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.StreamingClientResponse) async throws -> Result + ) async throws -> Result where Result: Sendable { + let request = GRPCCore.ClientRequest( + message: message, + metadata: metadata + ) + return try await self.connectShimmer( + request: request, + options: options, + onResponse: handleResponse + ) + } + + /// Call the "DisconnectShimmer" method. + /// + /// - Parameters: + /// - message: request message to send. + /// - metadata: Additional metadata to send, defaults to empty. + /// - options: Options to apply to this RPC, defaults to `.defaults`. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func disconnectShimmer( + _ message: ShimmerBLEGRPC_Request, + metadata: GRPCCore.Metadata = [:], + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in + try response.message + } + ) async throws -> Result where Result: Sendable { + let request = GRPCCore.ClientRequest( + message: message, + metadata: metadata + ) + return try await self.disconnectShimmer( + request: request, + options: options, + onResponse: handleResponse + ) + } + + /// Call the "WriteBytesShimmer" method. + /// + /// - Parameters: + /// - message: request message to send. + /// - metadata: Additional metadata to send, defaults to empty. + /// - options: Options to apply to this RPC, defaults to `.defaults`. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func writeBytesShimmer( + _ message: ShimmerBLEGRPC_WriteBytes, + metadata: GRPCCore.Metadata = [:], + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in + try response.message + } + ) async throws -> Result where Result: Sendable { + let request = GRPCCore.ClientRequest( + message: message, + metadata: metadata + ) + return try await self.writeBytesShimmer( + request: request, + options: options, + onResponse: handleResponse + ) + } + + /// Call the "SayHello" method. + /// + /// - Parameters: + /// - message: request message to send. + /// - metadata: Additional metadata to send, defaults to empty. + /// - options: Options to apply to this RPC, defaults to `.defaults`. + /// - handleResponse: A closure which handles the response, the result of which is + /// returned to the caller. Returning from the closure will cancel the RPC if it + /// hasn't already finished. + /// - Returns: The result of `handleResponse`. + internal func sayHello( + _ message: ShimmerBLEGRPC_Request, + metadata: GRPCCore.Metadata = [:], + options: GRPCCore.CallOptions = .defaults, + onResponse handleResponse: @Sendable @escaping (GRPCCore.ClientResponse) async throws -> Result = { response in + try response.message + } + ) async throws -> Result where Result: Sendable { + let request = GRPCCore.ClientRequest( + message: message, + metadata: metadata + ) + return try await self.sayHello( + request: request, + options: options, + onResponse: handleResponse + ) + } +} \ No newline at end of file diff --git a/ShimmerBLEGrpc/Sources/Protos/ShimmerBLEGrpcAndPacketByteArray.pb.swift b/ShimmerBLEGrpc/Sources/Protos/ShimmerBLEGrpcAndPacketByteArray.pb.swift new file mode 100644 index 0000000..5a4f404 --- /dev/null +++ b/ShimmerBLEGrpc/Sources/Protos/ShimmerBLEGrpcAndPacketByteArray.pb.swift @@ -0,0 +1,445 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// swiftlint:disable all +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: ShimmerBLEGrpcAndPacketByteArray.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +///using +///protoc-3.13.0-win64 +///protoc-gen-grpc-java-1.32.1-windows-x86_64.exe +///.nuget\packages\grpc.tools\2.34.0\tools\windows_x64\grpc_csharp_plugin.exe + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +enum ShimmerBLEGRPC_BluetoothState: SwiftProtobuf.Enum, Swift.CaseIterable { + typealias RawValue = Int + case connected // = 0 + case connecting // = 1 + case disconnected // = 2 + case UNRECOGNIZED(Int) + + init() { + self = .connected + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .connected + case 1: self = .connecting + case 2: self = .disconnected + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .connected: return 0 + case .connecting: return 1 + case .disconnected: return 2 + case .UNRECOGNIZED(let i): return i + } + } + + // The compiler won't synthesize support with the UNRECOGNIZED case. + static let allCases: [ShimmerBLEGRPC_BluetoothState] = [ + .connected, + .connecting, + .disconnected, + ] + +} + +/// The response message containing the greetings +struct ShimmerBLEGRPC_Reply: Sendable { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var message: String = String() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// The request message containing the user's name. +struct ShimmerBLEGRPC_Request: Sendable { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var name: String = String() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct ShimmerBLEGRPC_WriteBytes: @unchecked Sendable { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var address: String = String() + + var byteToWrite: Data = Data() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct ShimmerBLEGRPC_StreamRequest: Sendable { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var message: String = String() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct ShimmerBLEGRPC_StateStatus: Sendable { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var state: ShimmerBLEGRPC_BluetoothState = .connected + + var message: String = String() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct ShimmerBLEGRPC_ObjectClusterByteArray: @unchecked Sendable { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var uuid: String = String() + + var bluetoothAddress: String = String() + + var communicationType: ShimmerBLEGRPC_ObjectClusterByteArray.CommunicationType = .bt + + var systemTime: Int64 = 0 + + var calibratedTimeStamp: Double = 0 + + var binaryData: Data = Data() + + var unknownFields = SwiftProtobuf.UnknownStorage() + + enum CommunicationType: SwiftProtobuf.Enum, Swift.CaseIterable { + typealias RawValue = Int + case bt // = 0 + case sd // = 1 + case radio802154 // = 2 + case UNRECOGNIZED(Int) + + init() { + self = .bt + } + + init?(rawValue: Int) { + switch rawValue { + case 0: self = .bt + case 1: self = .sd + case 2: self = .radio802154 + default: self = .UNRECOGNIZED(rawValue) + } + } + + var rawValue: Int { + switch self { + case .bt: return 0 + case .sd: return 1 + case .radio802154: return 2 + case .UNRECOGNIZED(let i): return i + } + } + + // The compiler won't synthesize support with the UNRECOGNIZED case. + static let allCases: [ShimmerBLEGRPC_ObjectClusterByteArray.CommunicationType] = [ + .bt, + .sd, + .radio802154, + ] + + } + + init() {} +} + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +fileprivate let _protobuf_package = "shimmerBLEGRPC" + +extension ShimmerBLEGRPC_BluetoothState: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "Connected"), + 1: .same(proto: "Connecting"), + 2: .same(proto: "Disconnected"), + ] +} + +extension ShimmerBLEGRPC_Reply: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".Reply" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "message"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.message) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.message.isEmpty { + try visitor.visitSingularStringField(value: self.message, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ShimmerBLEGRPC_Reply, rhs: ShimmerBLEGRPC_Reply) -> Bool { + if lhs.message != rhs.message {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension ShimmerBLEGRPC_Request: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".Request" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "name"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.name) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.name.isEmpty { + try visitor.visitSingularStringField(value: self.name, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ShimmerBLEGRPC_Request, rhs: ShimmerBLEGRPC_Request) -> Bool { + if lhs.name != rhs.name {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension ShimmerBLEGRPC_WriteBytes: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".WriteBytes" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "address"), + 2: .standard(proto: "byte_to_write"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.address) }() + case 2: try { try decoder.decodeSingularBytesField(value: &self.byteToWrite) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.address.isEmpty { + try visitor.visitSingularStringField(value: self.address, fieldNumber: 1) + } + if !self.byteToWrite.isEmpty { + try visitor.visitSingularBytesField(value: self.byteToWrite, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ShimmerBLEGRPC_WriteBytes, rhs: ShimmerBLEGRPC_WriteBytes) -> Bool { + if lhs.address != rhs.address {return false} + if lhs.byteToWrite != rhs.byteToWrite {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension ShimmerBLEGRPC_StreamRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".StreamRequest" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "message"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.message) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.message.isEmpty { + try visitor.visitSingularStringField(value: self.message, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ShimmerBLEGRPC_StreamRequest, rhs: ShimmerBLEGRPC_StreamRequest) -> Bool { + if lhs.message != rhs.message {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension ShimmerBLEGRPC_StateStatus: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".StateStatus" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "State"), + 2: .same(proto: "message"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularEnumField(value: &self.state) }() + case 2: try { try decoder.decodeSingularStringField(value: &self.message) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.state != .connected { + try visitor.visitSingularEnumField(value: self.state, fieldNumber: 1) + } + if !self.message.isEmpty { + try visitor.visitSingularStringField(value: self.message, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ShimmerBLEGRPC_StateStatus, rhs: ShimmerBLEGRPC_StateStatus) -> Bool { + if lhs.state != rhs.state {return false} + if lhs.message != rhs.message {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension ShimmerBLEGRPC_ObjectClusterByteArray: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = _protobuf_package + ".ObjectClusterByteArray" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "uuid"), + 2: .same(proto: "bluetoothAddress"), + 3: .same(proto: "communicationType"), + 4: .same(proto: "systemTime"), + 5: .same(proto: "calibratedTimeStamp"), + 6: .standard(proto: "binary_data"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularStringField(value: &self.uuid) }() + case 2: try { try decoder.decodeSingularStringField(value: &self.bluetoothAddress) }() + case 3: try { try decoder.decodeSingularEnumField(value: &self.communicationType) }() + case 4: try { try decoder.decodeSingularInt64Field(value: &self.systemTime) }() + case 5: try { try decoder.decodeSingularDoubleField(value: &self.calibratedTimeStamp) }() + case 6: try { try decoder.decodeSingularBytesField(value: &self.binaryData) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.uuid.isEmpty { + try visitor.visitSingularStringField(value: self.uuid, fieldNumber: 1) + } + if !self.bluetoothAddress.isEmpty { + try visitor.visitSingularStringField(value: self.bluetoothAddress, fieldNumber: 2) + } + if self.communicationType != .bt { + try visitor.visitSingularEnumField(value: self.communicationType, fieldNumber: 3) + } + if self.systemTime != 0 { + try visitor.visitSingularInt64Field(value: self.systemTime, fieldNumber: 4) + } + if self.calibratedTimeStamp.bitPattern != 0 { + try visitor.visitSingularDoubleField(value: self.calibratedTimeStamp, fieldNumber: 5) + } + if !self.binaryData.isEmpty { + try visitor.visitSingularBytesField(value: self.binaryData, fieldNumber: 6) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ShimmerBLEGRPC_ObjectClusterByteArray, rhs: ShimmerBLEGRPC_ObjectClusterByteArray) -> Bool { + if lhs.uuid != rhs.uuid {return false} + if lhs.bluetoothAddress != rhs.bluetoothAddress {return false} + if lhs.communicationType != rhs.communicationType {return false} + if lhs.systemTime != rhs.systemTime {return false} + if lhs.calibratedTimeStamp != rhs.calibratedTimeStamp {return false} + if lhs.binaryData != rhs.binaryData {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension ShimmerBLEGRPC_ObjectClusterByteArray.CommunicationType: SwiftProtobuf._ProtoNameProviding { + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "BT"), + 1: .same(proto: "SD"), + 2: .same(proto: "Radio_802_15_4"), + ] +} diff --git a/ShimmerBLEGrpc/Sources/ShimmerBLEService.swift b/ShimmerBLEGrpc/Sources/ShimmerBLEService.swift new file mode 100644 index 0000000..3874b6e --- /dev/null +++ b/ShimmerBLEGrpc/Sources/ShimmerBLEService.swift @@ -0,0 +1,197 @@ +// +// ShimmerBLEService.swift +// ShimmerBLEGrpc +// +// Created by Joseph Yong on 09/04/2025. +// + +import Combine +import CoreBluetooth +import ShimmerBluetooth +import ArgumentParser +import GRPCCore +import GRPCNIOTransportHTTP2 +import GRPCProtobuf + +final class ShimmerBLEService: ShimmerBLEGRPC_ShimmerBLEByteServer.SimpleServiceProtocol { + + private var centralManager: CBCentralManager? + private var bluetoothManager: BluetoothManager? + private var deviceNameToConnect: String = "" + private var isConnecting: Bool = false + + //The key for all Dictionaries below is the Bluetooth device name + private var bluetoothDeviceMap = [String: CBPeripheral]() //stores the currently connected devices + private var queueMap = [String: ConcurrentQueue]() //stores the received bytes from connected devices which are written back to gRPC client in getDataStream() + private var connectStreamMap = [String: GRPCCore.RPCWriter]() //stores the writers for the status streams back to gRPC client + private var radioMap = [String: BleByteRadio]() + + init() { + self.centralManager = CBCentralManager() + self.bluetoothManager = BluetoothManager(centralmanager: self.centralManager!) + bluetoothManager?.delegate = self + } + + func sayHello(request: ShimmerBLEGRPC_Request, context: GRPCCore.ServerContext) async throws -> ShimmerBLEGRPC_Reply { + return ShimmerBLEGRPC_Reply.with { + $0.message = "Hello " + request.name + } + } + + func writeBytesShimmer(request: ShimmerBLEGRPC_WriteBytes, context: GRPCCore.ServerContext) async throws -> ShimmerBLEGRPC_Reply { + radioMap[request.address]!.writeData(data: request.byteToWrite) + return ShimmerBLEGRPC_Reply.with { + $0.message = "Written " + request.address + } + } + + func disconnectShimmer(request: ShimmerBLEGRPC_Request, context: GRPCCore.ServerContext) async throws -> ShimmerBLEGRPC_Reply { + print("Received disconnectShimmer request for: " + request.name) + startDisconnectShimmer(name: request.name) + return ShimmerBLEGRPC_Reply.with { + $0.message = "Disconnect " + request.name + } + } + + //Initiates a BLE scan first, before completing the process in startConnectShimmer() + func connectShimmer(request: ShimmerBLEGRPC_Request, response: GRPCCore.RPCWriter, context: GRPCCore.ServerContext) async throws { + if(!isConnecting) { + deviceNameToConnect = request.name + isConnecting = true + print("Received connectShimmer request for: " + deviceNameToConnect) + var res = self.bluetoothManager?.startScanning(deviceName: self.deviceNameToConnect, timeout: 3) + + connectStreamMap[deviceNameToConnect] = response + await writeStatusResponse(deviceName: deviceNameToConnect, state: ShimmerBLEGRPC_BluetoothState.connecting, message: "Connecting") + + try await Task.sleep(for: .seconds(4)) + while(bluetoothDeviceMap.keys.contains(deviceNameToConnect)) { + //this keeps the response GRPCCore.RPCWriter<> open + try await Task.sleep(for: .seconds(0.1)) //sleep 100ms + } + } else { + print("Received connectShimmer request for: " + deviceNameToConnect) + print("Error: connection attempt already in progress!") + await writeStatusResponseWithRPCWriter(state: ShimmerBLEGRPC_BluetoothState.disconnected, message: "Connection failed! Existing connection attempt in progress", writer: response) + } + } + + private func writeStatusResponse(deviceName: String, state: ShimmerBLEGRPC_BluetoothState, message: String) async { + let stateStatusStream = connectStreamMap[deviceName] + await writeStatusResponseWithRPCWriter(state: state, message: message, writer: stateStatusStream) + } + + private func writeStatusResponseWithRPCWriter(state: ShimmerBLEGRPC_BluetoothState, message: String, writer: GRPCCore.RPCWriter?) async { + if(writer != nil) { + let status = ShimmerBLEGRPC_StateStatus.with { + $0.state = state + $0.message = message + } + do { + try await writer?.write(status) + } catch let error { + print(error) + } + } + } + + //Currently unused + func sendDataStream(request: GRPCCore.RPCAsyncSequence, context: GRPCCore.ServerContext) async throws -> ShimmerBLEGRPC_Reply { + let reply = ShimmerBLEGRPC_Reply() + return reply + } + + //Currently unused + func getTestDataStream(request: ShimmerBLEGRPC_StreamRequest, response: GRPCCore.RPCWriter, context: GRPCCore.ServerContext) async throws { + print("Received getTestDataStream request for: " + request.message) + } + + func getDataStream(request: ShimmerBLEGRPC_StreamRequest, response: GRPCCore.RPCWriter, context: GRPCCore.ServerContext) async throws { + print("Received getDataStream request for: " + request.message) + while(bluetoothDeviceMap.keys.contains(request.message)) { + if(queueMap.keys.contains(request.message)) { + var data = Data() + while(!queueMap[request.message]!.isEmpty) { + data.append(queueMap[request.message]?.dequeue() ?? Data()) + } + + let res = ShimmerBLEGRPC_ObjectClusterByteArray.with { + $0.bluetoothAddress = request.message + $0.binaryData = data + $0.calibratedTimeStamp = Double(Date().timeIntervalSince1970 * 1_000) //Unix timestamp in milliseconds + } + try await response.write(res) + } + + try await Task.sleep(for: .seconds(0.001)) //sleep 1ms + } + + } + + func startConnectShimmer() async { + let peripheral = bluetoothManager?.getPeripheral(deviceName: deviceNameToConnect) + if(peripheral != nil) { + bluetoothDeviceMap[deviceNameToConnect] = peripheral + queueMap[deviceNameToConnect] = ConcurrentQueue() + + let radio = BleByteRadio(deviceName: deviceNameToConnect,cbperipheral: peripheral!,bluetoothManager: bluetoothManager!) + radio.delegate = self + + let success = await radio.connect() + if(success ?? false) { + radioMap[deviceNameToConnect] = radio + await writeStatusResponse(deviceName: deviceNameToConnect, state: ShimmerBLEGRPC_BluetoothState.connected, message: "Success") + } else { + await writeStatusResponse(deviceName: deviceNameToConnect, state: ShimmerBLEGRPC_BluetoothState.disconnected, message: "Radio failed to connect") + } + } else { + await writeStatusResponse(deviceName: deviceNameToConnect, state: ShimmerBLEGRPC_BluetoothState.disconnected, message: "Failed to discover device") + } + + isConnecting = false + } + + func startDisconnectShimmer(name: String) { + Task { + await radioMap[name]?.disconnect() + bluetoothDeviceMap.removeValue(forKey: name) + connectStreamMap.removeValue(forKey: name) + queueMap.removeValue(forKey: name) + radioMap.removeValue(forKey: name) + } + } + +} + +extension ShimmerBLEService : BluetoothManagerDelegate { + func scanCompleted() { + if(isConnecting) { + Task { + await startConnectShimmer() + } + } + } + + func isConnected() { + print("Bluetooth Manager Connected Device") + } + + func isDisconnected() { + print("Bluetooth Manager Disconnected Device") + } +} + +extension ShimmerBLEService : ByteCommunicationDelegate { + func byteCommunicationConnected() { + } + + func byteCommunicationDisconnected(connectionloss: Bool) { + } + + func byteCommunicationDataReceived(data: Data?, deviceName: String) { + let queue = queueMap[deviceName] + if(data != nil) { + queue?.enqueue(data ?? Data()) + } + } +} diff --git a/ShimmerBLEGrpc/Sources/ShimmerServer.swift b/ShimmerBLEGrpc/Sources/ShimmerServer.swift new file mode 100644 index 0000000..5428116 --- /dev/null +++ b/ShimmerBLEGrpc/Sources/ShimmerServer.swift @@ -0,0 +1,36 @@ +// +// ShimmerServer.swift +// ShimmerBLEGrpc +// +// Created by Joseph Yong on 24/04/2025. +// + +import ArgumentParser +import GRPCCore +import GRPCNIOTransportHTTP2 +import GRPCProtobuf + +@main +struct ShimmerServer: AsyncParsableCommand { + static let configuration = CommandConfiguration(abstract: "Starts the Shimmer BLE gRPC server.") + + @Option(help: "The port to listen on") + var port: Int = 50052 + + func run() async throws { + let server = GRPCServer( + transport: .http2NIOPosix( + address: .ipv4(host: "127.0.0.1", port: self.port), + transportSecurity: .plaintext + ), + services: [ShimmerBLEService()] + ) + + try await withThrowingDiscardingTaskGroup { group in + group.addTask { try await server.serve() } + if let address = try await server.listeningAddress { + print("Shimmer BLE gRPC listening on \(address)") + } + } + } +} diff --git a/ShimmerBLEGrpc/Sources/Subcommands/Serve.swift b/ShimmerBLEGrpc/Sources/Subcommands/Serve.swift new file mode 100644 index 0000000..7268705 --- /dev/null +++ b/ShimmerBLEGrpc/Sources/Subcommands/Serve.swift @@ -0,0 +1,44 @@ +/* + * Copyright 2024, gRPC Authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import ArgumentParser +import GRPCCore +import GRPCNIOTransportHTTP2 +import GRPCProtobuf + +struct Serve: AsyncParsableCommand { + static let configuration = CommandConfiguration(abstract: "Starts the Shimmer BLE gRPC server.") + + @Option(help: "The port to listen on") + var port: Int = 50052 + + func run() async throws { + let server = GRPCServer( + transport: .http2NIOPosix( + address: .ipv4(host: "127.0.0.1", port: self.port), + transportSecurity: .plaintext + ), + services: [ShimmerBLEService()] + ) + + try await withThrowingDiscardingTaskGroup { group in + group.addTask { try await server.serve() } + if let address = try await server.listeningAddress { + print("Shimmer BLE gRPC listening on \(address)") + } + } + } +} diff --git a/ShimmerBluetooth/ShimmerBluetooth.xcodeproj/project.pbxproj b/ShimmerBluetooth/ShimmerBluetooth.xcodeproj/project.pbxproj index 15f0edf..1fb2cc5 100644 --- a/ShimmerBluetooth/ShimmerBluetooth.xcodeproj/project.pbxproj +++ b/ShimmerBluetooth/ShimmerBluetooth.xcodeproj/project.pbxproj @@ -37,6 +37,7 @@ 3AED206D2B0B10960066A0F8 /* ShimmerUtilitiesTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AED206C2B0B10960066A0F8 /* ShimmerUtilitiesTest.swift */; }; 3AED20712B0C4BA60066A0F8 /* MagSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AED20702B0C4BA60066A0F8 /* MagSensor.swift */; }; 3AED20732B0C587B0066A0F8 /* GyroSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AED20722B0C587B0066A0F8 /* GyroSensor.swift */; }; + 451EC81A2DACCFFE00D8F269 /* ConcurrentQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 451EC8192DACCFF900D8F269 /* ConcurrentQueue.swift */; }; 92150EF52DE461CE00FEA53B /* AltMagSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92150EF42DE461CE00FEA53B /* AltMagSensor.swift */; }; 9299E50E2B85054E001EEFE0 /* PressureTempSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9299E50D2B85054E001EEFE0 /* PressureTempSensor.swift */; }; 9299E5102B850571001EEFE0 /* BattVoltageSensor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9299E50F2B850571001EEFE0 /* BattVoltageSensor.swift */; }; @@ -85,6 +86,7 @@ 3AED206C2B0B10960066A0F8 /* ShimmerUtilitiesTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShimmerUtilitiesTest.swift; sourceTree = ""; }; 3AED20702B0C4BA60066A0F8 /* MagSensor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MagSensor.swift; sourceTree = ""; }; 3AED20722B0C587B0066A0F8 /* GyroSensor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GyroSensor.swift; sourceTree = ""; }; + 451EC8192DACCFF900D8F269 /* ConcurrentQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConcurrentQueue.swift; sourceTree = ""; }; 92150EF42DE461CE00FEA53B /* AltMagSensor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AltMagSensor.swift; sourceTree = ""; }; 9299E50D2B85054E001EEFE0 /* PressureTempSensor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PressureTempSensor.swift; sourceTree = ""; }; 9299E50F2B850571001EEFE0 /* BattVoltageSensor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BattVoltageSensor.swift; sourceTree = ""; }; @@ -133,6 +135,7 @@ 3A780C872AE12BEB00EAF050 /* ShimmerBluetooth */ = { isa = PBXGroup; children = ( + 451EC8192DACCFF900D8F269 /* ConcurrentQueue.swift */, 92150EF42DE461CE00FEA53B /* AltMagSensor.swift */, 3AEB12F82BCE6F7E00B5F6F1 /* Shimmer3SpeedTestProtocol.swift */, 3A780C882AE12BEB00EAF050 /* ShimmerBluetooth.h */, @@ -297,6 +300,7 @@ 3A780CDA2AE12D8300EAF050 /* VerisenseProtocol.swift in Sources */, 3AED20732B0C587B0066A0F8 /* GyroSensor.swift in Sources */, 92B1067A2B7DAFBC00AB9952 /* EXGSensor.swift in Sources */, + 451EC81A2DACCFFE00D8F269 /* ConcurrentQueue.swift in Sources */, 3A7712892AE1773E006213A8 /* BluetoothManager.swift in Sources */, 9299E5102B850571001EEFE0 /* BattVoltageSensor.swift in Sources */, 3AB320E62B070830003D94F8 /* Sensor.swift in Sources */, @@ -468,10 +472,13 @@ 3A780C9A2AE12BEB00EAF050 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=macosx*]" = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -510,10 +517,13 @@ 3A780C9B2AE12BEB00EAF050 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=macosx*]" = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; diff --git a/ShimmerBluetooth/ShimmerBluetooth/BleByteRadio.swift b/ShimmerBluetooth/ShimmerBluetooth/BleByteRadio.swift index 3584a4f..1155d76 100644 --- a/ShimmerBluetooth/ShimmerBluetooth/BleByteRadio.swift +++ b/ShimmerBluetooth/ShimmerBluetooth/BleByteRadio.swift @@ -104,6 +104,14 @@ public class BleByteRadio : NSObject, ByteCommunication { return true } + public func writeData(data: Data) ->Bool { + guard let char = self.characteristics[RBL_CHAR_TX_UUID] else { return false} + print("[DEBUG] Write Data \(data)") + print(char.uuid.uuidString) + self.activePeripheral?.writeValue(data, for: char, type: .withResponse) + return true + } + public func enableNotifications(enable: Bool) { guard let char = self.characteristics[RBL_CHAR_RX_UUID] else { return } @@ -273,8 +281,8 @@ extension BleByteRadio : CBPeripheralDelegate { if characteristic.uuid.uuidString == RBL_CHAR_RX_UUID { if let data = characteristic.value { //self.processData(data) - print(data) - self.delegate?.byteCommunicationDataReceived(data: data) +// print(data) + self.delegate?.byteCommunicationDataReceived(data: data, deviceName: (deviceName ?? "")) } } } diff --git a/ShimmerBluetooth/ShimmerBluetooth/BluetoothManager.swift b/ShimmerBluetooth/ShimmerBluetooth/BluetoothManager.swift index 963a305..fe79042 100644 --- a/ShimmerBluetooth/ShimmerBluetooth/BluetoothManager.swift +++ b/ShimmerBluetooth/ShimmerBluetooth/BluetoothManager.swift @@ -33,12 +33,11 @@ public class BluetoothManager: NSObject { } @objc private func scanTimeout() { - print("[DEBUG] Scanning stopped") self.centralManager.stopScan() self.delegate?.scanCompleted() } - + public func startScanning(uuid:String, timeout: Double) -> Bool { deviceName = "" if self.centralManager.state != .poweredOn { @@ -50,7 +49,9 @@ public class BluetoothManager: NSObject { print("[DEBUG] Scanning started") // CBCentralManagerScanOptionAllowDuplicatesKey - timer = Timer.scheduledTimer(timeInterval: timeout, target: self, selector: #selector(BluetoothManager.scanTimeout), userInfo: nil, repeats: false) + DispatchQueue.main.async { + self.timer = Timer.scheduledTimer(timeInterval: timeout, target: self, selector: #selector(BluetoothManager.scanTimeout), userInfo: nil, repeats: false) + } self.centralManager.scanForPeripherals(withServices: [CBUUID(string: uuid)], options: nil) //self.centralManager.scanForPeripherals(withServices: nil, options: nil) print(self.centralManager.isScanning) @@ -68,7 +69,9 @@ public class BluetoothManager: NSObject { print("[DEBUG] Scanning started") // CBCentralManagerScanOptionAllowDuplicatesKey - timer = Timer.scheduledTimer(timeInterval: timeout, target: self, selector: #selector(BluetoothManager.scanTimeout), userInfo: nil, repeats: false) + DispatchQueue.main.async { + self.timer = Timer.scheduledTimer(timeInterval: timeout, target: self, selector: #selector(BluetoothManager.scanTimeout), userInfo: nil, repeats: false) + } //self.centralManager.scanForPeripherals(withServices: [CBUUID(string: uuid)], options: nil) self.centralManager.scanForPeripherals(withServices: nil, options: nil) print(self.centralManager.isScanning) @@ -86,7 +89,9 @@ public class BluetoothManager: NSObject { print("[DEBUG] Scanning started") // CBCentralManagerScanOptionAllowDuplicatesKey - timer = Timer.scheduledTimer(timeInterval: timeout, target: self, selector: #selector(BluetoothManager.scanTimeout), userInfo: nil, repeats: false) + DispatchQueue.main.async { + self.timer = Timer.scheduledTimer(timeInterval: timeout, target: self, selector: #selector(BluetoothManager.scanTimeout), userInfo: nil, repeats: false) + } //self.centralManager.scanForPeripherals(withServices: [CBUUID(string: uuid)], options: nil) self.centralManager.scanForPeripherals(withServices: nil, options: nil) print(self.centralManager.isScanning) diff --git a/ShimmerBluetooth/ShimmerBluetooth/ByteCommunication.swift b/ShimmerBluetooth/ShimmerBluetooth/ByteCommunication.swift index 34e430f..f2121ab 100644 --- a/ShimmerBluetooth/ShimmerBluetooth/ByteCommunication.swift +++ b/ShimmerBluetooth/ShimmerBluetooth/ByteCommunication.swift @@ -16,5 +16,5 @@ public protocol ByteCommunication { public protocol ByteCommunicationDelegate { func byteCommunicationConnected() func byteCommunicationDisconnected(connectionloss: Bool) - func byteCommunicationDataReceived(data: Data?) + func byteCommunicationDataReceived(data: Data?, deviceName: String) } diff --git a/ShimmerBluetooth/ShimmerBluetooth/ConcurrentQueue.swift b/ShimmerBluetooth/ShimmerBluetooth/ConcurrentQueue.swift new file mode 100644 index 0000000..099d32f --- /dev/null +++ b/ShimmerBluetooth/ShimmerBluetooth/ConcurrentQueue.swift @@ -0,0 +1,46 @@ +// +// ConcurrentQueue.swift +// ShimmerBluetooth +// +// Created by Joseph Yong on 14/04/2025. +// + +import Foundation + +public class ConcurrentQueue { + private var queue: [T] = [] + private let dispatchQueue = DispatchQueue(label: "com.concurrentQueue", attributes: .concurrent) + + public init() { } + + public func enqueue(_ element: T) { + dispatchQueue.sync(flags: .barrier) { + self.queue.append(element) + } + } + + public func dequeue() -> T? { + return dispatchQueue.sync(flags: .barrier) { + guard !self.queue.isEmpty else { return nil } + return self.queue.removeFirst() + } + } + + func peek() -> T? { + return dispatchQueue.sync { + return queue.first + } + } + + public var isEmpty: Bool { + return dispatchQueue.sync { + return queue.isEmpty + } + } + + var count: Int { + return dispatchQueue.sync { + return queue.count + } + } +} diff --git a/ShimmerBluetooth/ShimmerBluetooth/Shimmer3Protocol.swift b/ShimmerBluetooth/ShimmerBluetooth/Shimmer3Protocol.swift index 58e44e2..d052460 100644 --- a/ShimmerBluetooth/ShimmerBluetooth/Shimmer3Protocol.swift +++ b/ShimmerBluetooth/ShimmerBluetooth/Shimmer3Protocol.swift @@ -1808,7 +1808,7 @@ extension Shimmer3Protocol : ByteCommunicationDelegate { print("Current State: \(BTState)") } - public func byteCommunicationDataReceived(data: Data?) { + public func byteCommunicationDataReceived(data: Data?, deviceName: String) { self.processData(data!) } diff --git a/ShimmerBluetooth/ShimmerBluetooth/Shimmer3SpeedTestProtocol.swift b/ShimmerBluetooth/ShimmerBluetooth/Shimmer3SpeedTestProtocol.swift index b545557..bf40a09 100644 --- a/ShimmerBluetooth/ShimmerBluetooth/Shimmer3SpeedTestProtocol.swift +++ b/ShimmerBluetooth/ShimmerBluetooth/Shimmer3SpeedTestProtocol.swift @@ -155,7 +155,7 @@ extension Shimmer3SpeedTestProtocol : ByteCommunicationDelegate { stopProcessing() } - public func byteCommunicationDataReceived(data: Data?) { + public func byteCommunicationDataReceived(data: Data?, deviceName: String) { self.processData(data!) } diff --git a/ShimmerBluetooth/ShimmerBluetooth/VerisenseProtocol.swift b/ShimmerBluetooth/ShimmerBluetooth/VerisenseProtocol.swift index b98cfdf..7f25c59 100644 --- a/ShimmerBluetooth/ShimmerBluetooth/VerisenseProtocol.swift +++ b/ShimmerBluetooth/ShimmerBluetooth/VerisenseProtocol.swift @@ -146,7 +146,7 @@ extension VerisenseProtocol : ByteCommunicationDelegate { } - public func byteCommunicationDataReceived(data: Data?) { + public func byteCommunicationDataReceived(data: Data?, deviceName: String) { self.processData(data!) self.continuation?.resume(returning: true) self.continuation = nil