diff --git a/DJI-UXSDK-iOS-Beta-Communication.podspec b/DJI-UXSDK-iOS-Beta-Communication.podspec index 5012157..aab12a2 100644 --- a/DJI-UXSDK-iOS-Beta-Communication.podspec +++ b/DJI-UXSDK-iOS-Beta-Communication.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'DJI-UXSDK-iOS-Beta-Communication' - s.version = '0.1.0' + s.version = '0.1.1' s.license = 'MIT' s.summary = 'Intra-framework, and system communication infrastructure for DJI iOS UX SDK.' s.homepage = 'https://github.com/dji-sdk/Mobile-UXSDK-Beta-iOS' diff --git a/DJI-UXSDK-iOS-Beta-Core.podspec b/DJI-UXSDK-iOS-Beta-Core.podspec index 3b2a5f0..9f7db36 100644 --- a/DJI-UXSDK-iOS-Beta-Core.podspec +++ b/DJI-UXSDK-iOS-Beta-Core.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'DJI-UXSDK-iOS-Beta-Core' - s.version = '0.1.0' + s.version = '0.1.1' s.license = 'MIT' s.summary = 'Core utilities for DJI iOS UX SDK.' s.homepage = 'https://github.com/dji-sdk/Mobile-UXSDK-Beta-iOS' @@ -15,6 +15,6 @@ Pod::Spec.new do |s| s.cocoapods_version = '>= 1.7.1' s.source_files = 'DJIUXSDKCore/**/*.{h,m}' s.public_header_files = 'DJIUXSDKCore/**/*.h' - s.dependency 'DJI-SDK-iOS', '4.10' - s.dependency 'DJI-UXSDK-iOS-Beta-Communication', '0.1.0' -end \ No newline at end of file + s.dependency 'DJI-SDK-iOS', '4.11' + s.dependency 'DJI-UXSDK-iOS-Beta-Communication', '0.1.1' +end diff --git a/DJI-UXSDK-iOS-Beta-Widgets.podspec b/DJI-UXSDK-iOS-Beta-Widgets.podspec index 0949339..150247e 100644 --- a/DJI-UXSDK-iOS-Beta-Widgets.podspec +++ b/DJI-UXSDK-iOS-Beta-Widgets.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'DJI-UXSDK-iOS-Beta-Widgets' - s.version = '0.1.0' + s.version = '0.1.1' s.license = 'MIT' s.summary = 'A collection of widget, widget model, and related helpers for DJI iOS UX SDK.' s.homepage = 'https://github.com/dji-sdk/Mobile-UXSDK-Beta-iOS' @@ -15,7 +15,7 @@ Pod::Spec.new do |s| s.cocoapods_version = '>= 1.7.1' s.source_files = 'DJIUXSDKWidgets/**/*.{h,m}' s.resource_bundle = { 'DUXBetaAssets' => 'DJIUXSDKWidgets/**/*.xcassets' } - s.dependency 'DJI-SDK-iOS', '4.10' - s.dependency 'DJI-UXSDK-iOS-Beta-Core', '0.1.0' - s.dependency 'DJI-UXSDK-iOS-Beta-Communication', '0.1.0' -end \ No newline at end of file + s.dependency 'DJI-SDK-iOS', '4.11' + s.dependency 'DJI-UXSDK-iOS-Beta-Core', '0.1.1' + s.dependency 'DJI-UXSDK-iOS-Beta-Communication', '0.1.1' +end diff --git a/DJI-UXSDK-iOS-Beta.podspec b/DJI-UXSDK-iOS-Beta.podspec index a5666f8..6b94570 100644 --- a/DJI-UXSDK-iOS-Beta.podspec +++ b/DJI-UXSDK-iOS-Beta.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'DJI-UXSDK-iOS-Beta' - s.version = '0.1.0' + s.version = '0.1.1' s.license = 'MIT' s.summary = 'DJI iOS UX SDK' s.homepage = 'https://github.com/dji-sdk/Mobile-UXSDK-Beta-iOS' @@ -14,7 +14,7 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { 'ENABLE_BITCODE' => 'NO', 'DEFINES_MODULE' => 'YES', 'SWIFT_OBJC_BRIDGING_HEADER' => '$(PODS_TARGET_SRCROOT)/'} s.cocoapods_version = '>= 1.7.1' s.source_files = 'DJIUXSDKBeta/**/*.{h,m}' - s.dependency 'DJI-UXSDK-iOS-Beta-Core', '0.1.0' - s.dependency 'DJI-UXSDK-iOS-Beta-Communication', '0.1.0' - s.dependency 'DJI-UXSDK-iOS-Beta-Widgets', '0.1.0' -end \ No newline at end of file + s.dependency 'DJI-UXSDK-iOS-Beta-Core', '0.1.1' + s.dependency 'DJI-UXSDK-iOS-Beta-Communication', '0.1.1' + s.dependency 'DJI-UXSDK-iOS-Beta-Widgets', '0.1.1' +end diff --git a/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaCommand.h b/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaCommand.h index dc7dc76..977393b 100644 --- a/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaCommand.h +++ b/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaCommand.h @@ -1,8 +1,28 @@ // // NSObject+DUXBetaCommand.h // DJIUXSDK -// -// Copyright © 2018-2019 DJI. All rights reserved. +// +// MIT License +// +// Copyright © 2018-2019 DJI +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. // #import diff --git a/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaMapping.h b/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaMapping.h index 8a79249..916c255 100644 --- a/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaMapping.h +++ b/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaMapping.h @@ -1,8 +1,28 @@ // // NSObject+DUXBetaMapping.h // DJIUXSDK -// -// Copyright © 2018-2019 DJI. All rights reserved. +// +// MIT License +// +// Copyright © 2018-2019 DJI +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. // #import diff --git a/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaMapping.m b/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaMapping.m index 9b00c9e..d4ef7ce 100644 --- a/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaMapping.m +++ b/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaMapping.m @@ -1,8 +1,28 @@ // // NSObject+DUXBetaMapping.m // DJIUXSDK -// -// Copyright © 2018-2019 DJI. All rights reserved. +// +// MIT License +// +// Copyright © 2018-2019 DJI +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. // #import "NSObject+DUXBetaMapping.h" diff --git a/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaRKVOExtension.h b/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaRKVOExtension.h index a0850a9..dd02ac4 100644 --- a/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaRKVOExtension.h +++ b/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaRKVOExtension.h @@ -1,8 +1,28 @@ // // NSObject+DUXBetaRKVOExtension.h // DJIUXSDK -// -// Copyright © 2018-2019 DJI. All rights reserved. +// +// MIT License +// +// Copyright © 2018-2019 DJI +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. // diff --git a/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaRKVOExtension.m b/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaRKVOExtension.m index 8413b09..971794d 100644 --- a/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaRKVOExtension.m +++ b/DJIUXSDKCore/BindingConvenienceCategories/NSObject+DUXBetaRKVOExtension.m @@ -1,8 +1,28 @@ // // NSObject+DUXBetaRKVOExtension.m // DJIUXSDK -// -// Copyright © 2018-2019 DJI. All rights reserved. +// +// MIT License +// +// Copyright © 2018-2019 DJI +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. // #import "NSObject+DUXBetaRKVOExtension.h" diff --git a/DJIUXSDKWidgets/VisionWidget/DUXBetaVisionWidget.h b/DJIUXSDKWidgets/VisionWidget/DUXBetaVisionWidget.h index cefc3d9..93c8742 100644 --- a/DJIUXSDKWidgets/VisionWidget/DUXBetaVisionWidget.h +++ b/DJIUXSDKWidgets/VisionWidget/DUXBetaVisionWidget.h @@ -1,8 +1,28 @@ // // DUXBetaVisionWidget.h // DJIUXSDK -// -// Copyright © 2018-2019 DJI. All rights reserved. +// +// MIT License +// +// Copyright © 2018-2019 DJI +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. // #import diff --git a/DJIUXSDKWidgets/VisionWidget/DUXBetaVisionWidget.m b/DJIUXSDKWidgets/VisionWidget/DUXBetaVisionWidget.m index c85873e..5e0660f 100644 --- a/DJIUXSDKWidgets/VisionWidget/DUXBetaVisionWidget.m +++ b/DJIUXSDKWidgets/VisionWidget/DUXBetaVisionWidget.m @@ -1,8 +1,28 @@ // // DUXBetaVisionWidget.m // DJIUXSDK -// -// Copyright © 2018-2019 DJI. All rights reserved. +// +// MIT License +// +// Copyright © 2018-2019 DJI +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. // #import "DUXBetaVisionWidget.h" diff --git a/UXSDKBetaSample/Podfile b/UXSDKBetaSample/Podfile index 5f88091..6d0367a 100644 --- a/UXSDKBetaSample/Podfile +++ b/UXSDKBetaSample/Podfile @@ -2,8 +2,9 @@ platform :ios, '11.0' target 'UXSDKBetaSample' do use_frameworks! - pod 'DJI-SDK-iOS', '~> 4.10' - pod 'DJI-UXSDK-iOS', '~> 4.10' - pod 'DJIWidget', '~> 1.5' - pod 'DJI-UXSDK-iOS-Beta', '~> 0.1.0' -end \ No newline at end of file + pod 'DJI-SDK-iOS', '~> 4.11' + pod 'DJI-UXSDK-iOS', '~> 4.11' + pod 'DJIWidget', '~> 1.6.1' + pod 'DJI-UXSDK-iOS-Beta', '~> 0.1.1' + pod 'iOS-Color-Picker' +end diff --git a/UXSDKBetaSample/UXSDKBetaSample.xcodeproj/project.pbxproj b/UXSDKBetaSample/UXSDKBetaSample.xcodeproj/project.pbxproj index fdc7256..d2a9ce1 100644 --- a/UXSDKBetaSample/UXSDKBetaSample.xcodeproj/project.pbxproj +++ b/UXSDKBetaSample/UXSDKBetaSample.xcodeproj/project.pbxproj @@ -15,11 +15,13 @@ 537AA97D2265344300905FCC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 537AA97C2265344200905FCC /* AppDelegate.swift */; }; 537AA991226534AA00905FCC /* SingleWidgetViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 537AA98A226534AA00905FCC /* SingleWidgetViewController.swift */; }; 537AA992226534AA00905FCC /* LogCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 537AA98C226534AA00905FCC /* LogCenter.swift */; }; - 537AA993226534AA00905FCC /* ProductCommunicationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 537AA98D226534AA00905FCC /* ProductCommunicationManager.swift */; }; + 537AA993226534AA00905FCC /* ProductCommunicationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 537AA98D226534AA00905FCC /* ProductCommunicationService.swift */; }; 537AA994226534AA00905FCC /* LogEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 537AA98E226534AA00905FCC /* LogEntry.swift */; }; 537AA995226534AA00905FCC /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 537AA98F226534AA00905FCC /* MainViewController.swift */; }; 537AA996226534AA00905FCC /* WidgetsListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 537AA990226534AA00905FCC /* WidgetsListViewController.swift */; }; - A884E0421F33C978D173A425 /* Pods_UXSDKBetaSample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB9CD7396257BA97511570C0 /* Pods_UXSDKBetaSample.framework */; }; + 53A5E36D2344013700313B15 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A5E36C2344013700313B15 /* Helpers.swift */; }; + 53A5E37223441CC800313B15 /* CustomMapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A5E37123441CC800313B15 /* CustomMapViewController.swift */; }; + C97EF7DCF3F3C81B3B3AB4D9 /* Pods_UXSDKBetaSample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A026F0CA3230C6AC37EB63EE /* Pods_UXSDKBetaSample.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -33,8 +35,6 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 06CD3653D82C9464D05BAE55 /* Pods-UXSDKBetaSample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UXSDKBetaSample.debug.xcconfig"; path = "Target Support Files/Pods-UXSDKBetaSample/Pods-UXSDKBetaSample.debug.xcconfig"; sourceTree = ""; }; - 4A34B7F60322694B7B3C0C36 /* Pods-UXSDKBetaSample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UXSDKBetaSample.release.xcconfig"; path = "Target Support Files/Pods-UXSDKBetaSample/Pods-UXSDKBetaSample.release.xcconfig"; sourceTree = ""; }; 536C4BA122652AA8008E370B /* UXSDKBetaSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UXSDKBetaSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 536C4BAD22652AAA008E370B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 536C4BB222652AAA008E370B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -49,11 +49,15 @@ 537AA97C2265344200905FCC /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 537AA98A226534AA00905FCC /* SingleWidgetViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleWidgetViewController.swift; sourceTree = ""; }; 537AA98C226534AA00905FCC /* LogCenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogCenter.swift; sourceTree = ""; }; - 537AA98D226534AA00905FCC /* ProductCommunicationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProductCommunicationManager.swift; sourceTree = ""; }; + 537AA98D226534AA00905FCC /* ProductCommunicationService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProductCommunicationService.swift; sourceTree = ""; }; 537AA98E226534AA00905FCC /* LogEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogEntry.swift; sourceTree = ""; }; 537AA98F226534AA00905FCC /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; }; 537AA990226534AA00905FCC /* WidgetsListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WidgetsListViewController.swift; sourceTree = ""; }; - FB9CD7396257BA97511570C0 /* Pods_UXSDKBetaSample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_UXSDKBetaSample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 53A5E36C2344013700313B15 /* Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = ""; }; + 53A5E37123441CC800313B15 /* CustomMapViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomMapViewController.swift; sourceTree = ""; }; + 7D71737CF97A8704C6281A3B /* Pods-UXSDKBetaSample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UXSDKBetaSample.release.xcconfig"; path = "Target Support Files/Pods-UXSDKBetaSample/Pods-UXSDKBetaSample.release.xcconfig"; sourceTree = ""; }; + A026F0CA3230C6AC37EB63EE /* Pods_UXSDKBetaSample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_UXSDKBetaSample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B7D7223DB74FFB59D2B7B25A /* Pods-UXSDKBetaSample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UXSDKBetaSample.debug.xcconfig"; path = "Target Support Files/Pods-UXSDKBetaSample/Pods-UXSDKBetaSample.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -61,7 +65,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - A884E0421F33C978D173A425 /* Pods_UXSDKBetaSample.framework in Frameworks */, + C97EF7DCF3F3C81B3B3AB4D9 /* Pods_UXSDKBetaSample.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -75,11 +79,19 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 32A8964571722FADB1A813A3 /* Frameworks */ = { + isa = PBXGroup; + children = ( + A026F0CA3230C6AC37EB63EE /* Pods_UXSDKBetaSample.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 3A5F261302AC9ED5A40BF4DA /* Pods */ = { isa = PBXGroup; children = ( - 06CD3653D82C9464D05BAE55 /* Pods-UXSDKBetaSample.debug.xcconfig */, - 4A34B7F60322694B7B3C0C36 /* Pods-UXSDKBetaSample.release.xcconfig */, + B7D7223DB74FFB59D2B7B25A /* Pods-UXSDKBetaSample.debug.xcconfig */, + 7D71737CF97A8704C6281A3B /* Pods-UXSDKBetaSample.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -92,7 +104,7 @@ 536C4BBC22652AAA008E370B /* UXSDKSampleTests */, 536C4BA222652AA8008E370B /* Products */, 3A5F261302AC9ED5A40BF4DA /* Pods */, - B0861A724F685D4965C33316 /* Frameworks */, + 32A8964571722FADB1A813A3 /* Frameworks */, ); sourceTree = ""; }; @@ -114,6 +126,8 @@ 537AA98F226534AA00905FCC /* MainViewController.swift */, 537AA98B226534AA00905FCC /* Services */, 537AA98A226534AA00905FCC /* SingleWidgetViewController.swift */, + 53A5E36C2344013700313B15 /* Helpers.swift */, + 53A5E37123441CC800313B15 /* CustomMapViewController.swift */, 537AA990226534AA00905FCC /* WidgetsListViewController.swift */, 536C4BAD22652AAA008E370B /* Assets.xcassets */, 536C4BB222652AAA008E370B /* Info.plist */, @@ -144,20 +158,12 @@ isa = PBXGroup; children = ( 537AA98C226534AA00905FCC /* LogCenter.swift */, - 537AA98D226534AA00905FCC /* ProductCommunicationManager.swift */, + 537AA98D226534AA00905FCC /* ProductCommunicationService.swift */, 537AA98E226534AA00905FCC /* LogEntry.swift */, ); path = Services; sourceTree = ""; }; - B0861A724F685D4965C33316 /* Frameworks */ = { - isa = PBXGroup; - children = ( - FB9CD7396257BA97511570C0 /* Pods_UXSDKBetaSample.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -165,11 +171,11 @@ isa = PBXNativeTarget; buildConfigurationList = 536C4BC222652AAA008E370B /* Build configuration list for PBXNativeTarget "UXSDKBetaSample" */; buildPhases = ( - 725353F468B480DD15748481 /* [CP] Check Pods Manifest.lock */, + 7B767114A4EE26EDA22879A5 /* [CP] Check Pods Manifest.lock */, 536C4B9D22652AA8008E370B /* Sources */, 536C4B9E22652AA8008E370B /* Frameworks */, 536C4B9F22652AA8008E370B /* Resources */, - B72324519921484489A4BB7B /* [CP] Embed Pods Frameworks */, + C20598BE7C6A4A45B8CB1407 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -257,7 +263,7 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 725353F468B480DD15748481 /* [CP] Check Pods Manifest.lock */ = { + 7B767114A4EE26EDA22879A5 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -279,7 +285,7 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - B72324519921484489A4BB7B /* [CP] Embed Pods Frameworks */ = { + C20598BE7C6A4A45B8CB1407 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -305,8 +311,10 @@ files = ( 5379933D22AB14A5006FEE71 /* CustomSplitViewController.swift in Sources */, 537AA995226534AA00905FCC /* MainViewController.swift in Sources */, - 537AA993226534AA00905FCC /* ProductCommunicationManager.swift in Sources */, + 537AA993226534AA00905FCC /* ProductCommunicationService.swift in Sources */, 537AA991226534AA00905FCC /* SingleWidgetViewController.swift in Sources */, + 53A5E37223441CC800313B15 /* CustomMapViewController.swift in Sources */, + 53A5E36D2344013700313B15 /* Helpers.swift in Sources */, 537AA992226534AA00905FCC /* LogCenter.swift in Sources */, 537AA996226534AA00905FCC /* WidgetsListViewController.swift in Sources */, 537AA97D2265344300905FCC /* AppDelegate.swift in Sources */, @@ -472,7 +480,7 @@ }; 536C4BC322652AAA008E370B /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 06CD3653D82C9464D05BAE55 /* Pods-UXSDKBetaSample.debug.xcconfig */; + baseConfigurationReference = B7D7223DB74FFB59D2B7B25A /* Pods-UXSDKBetaSample.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; @@ -501,7 +509,7 @@ }; 536C4BC422652AAA008E370B /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4A34B7F60322694B7B3C0C36 /* Pods-UXSDKBetaSample.release.xcconfig */; + baseConfigurationReference = 7D71737CF97A8704C6281A3B /* Pods-UXSDKBetaSample.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; diff --git a/UXSDKBetaSample/UXSDKBetaSample/AppDelegate.swift b/UXSDKBetaSample/UXSDKBetaSample/AppDelegate.swift index f86a2bb..95f9809 100644 --- a/UXSDKBetaSample/UXSDKBetaSample/AppDelegate.swift +++ b/UXSDKBetaSample/UXSDKBetaSample/AppDelegate.swift @@ -29,10 +29,9 @@ import UIKit class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - public var productCommManager = ProductCommunicationManager() func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - self.productCommManager.registerWithProduct() + ProductCommunicationService.shared.registerWithProduct() return true } diff --git a/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/Aircraft.imageset/Aircraft@1x.png b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/Aircraft.imageset/Aircraft@1x.png new file mode 100644 index 0000000..22bf3e6 Binary files /dev/null and b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/Aircraft.imageset/Aircraft@1x.png differ diff --git a/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/Aircraft.imageset/Aircraft@2x.png b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/Aircraft.imageset/Aircraft@2x.png new file mode 100644 index 0000000..9343090 Binary files /dev/null and b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/Aircraft.imageset/Aircraft@2x.png differ diff --git a/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/Aircraft.imageset/Aircraft@3x.png b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/Aircraft.imageset/Aircraft@3x.png new file mode 100644 index 0000000..1c1bc48 Binary files /dev/null and b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/Aircraft.imageset/Aircraft@3x.png differ diff --git a/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/Aircraft.imageset/Contents.json b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/Aircraft.imageset/Contents.json new file mode 100644 index 0000000..60c8db2 --- /dev/null +++ b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/Aircraft.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Aircraft@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "Aircraft@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Aircraft@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/HomePoint.imageset/Contents.json b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/HomePoint.imageset/Contents.json new file mode 100644 index 0000000..e6ff9bd --- /dev/null +++ b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/HomePoint.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "HomePoint@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "HomePoint@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "HomePoint@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/HomePoint.imageset/HomePoint@1x.png b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/HomePoint.imageset/HomePoint@1x.png new file mode 100644 index 0000000..e8690b7 Binary files /dev/null and b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/HomePoint.imageset/HomePoint@1x.png differ diff --git a/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/HomePoint.imageset/HomePoint@2x.png b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/HomePoint.imageset/HomePoint@2x.png new file mode 100644 index 0000000..e8690b7 Binary files /dev/null and b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/HomePoint.imageset/HomePoint@2x.png differ diff --git a/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/HomePoint.imageset/HomePoint@3x.png b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/HomePoint.imageset/HomePoint@3x.png new file mode 100644 index 0000000..65ddda1 Binary files /dev/null and b/UXSDKBetaSample/UXSDKBetaSample/Assets.xcassets/HomePoint.imageset/HomePoint@3x.png differ diff --git a/UXSDKBetaSample/UXSDKBetaSample/Base.lproj/Main.storyboard b/UXSDKBetaSample/UXSDKBetaSample/Base.lproj/Main.storyboard index 2e61745..949cedd 100644 --- a/UXSDKBetaSample/UXSDKBetaSample/Base.lproj/Main.storyboard +++ b/UXSDKBetaSample/UXSDKBetaSample/Base.lproj/Main.storyboard @@ -1,11 +1,9 @@ - - - - + + - + @@ -15,7 +13,7 @@ - + @@ -35,7 +33,7 @@ - + @@ -178,7 +176,6 @@ - @@ -202,10 +199,10 @@ - + - + @@ -258,10 +255,10 @@ - + - + - - + @@ -515,7 +512,7 @@ - + @@ -545,7 +542,7 @@ - + @@ -559,7 +556,7 @@ - + @@ -569,5 +566,448 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/UXSDKBetaSample/UXSDKBetaSample/CustomMapViewController.swift b/UXSDKBetaSample/UXSDKBetaSample/CustomMapViewController.swift new file mode 100644 index 0000000..c49e2e5 --- /dev/null +++ b/UXSDKBetaSample/UXSDKBetaSample/CustomMapViewController.swift @@ -0,0 +1,516 @@ +// +// WidgetsListViewController.swift +// DJIUXSDK +// +// Copyright © 2018-2019 DJI +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +import UIKit +import DJIUXSDKBeta +import iOS_Color_Picker + +class CustomMapViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, FCColorPickerViewControllerDelegate { + + var mapWidget:DUXBetaMapWidget? + + @IBOutlet weak var mainStackView: UIStackView? + + @IBOutlet weak var widthSlider:UISlider? + @IBOutlet weak var alphaSlider:UISlider? + @IBOutlet weak var widthLabel:UILabel? + @IBOutlet weak var alphaLabel:UILabel? + + @IBOutlet weak var lockAircraftCameraSwitch:UISwitch? + @IBOutlet weak var lockHomeCameraSwitch:UISwitch? + @IBOutlet weak var showLegendSwitch:UISwitch? + + @IBOutlet weak var flyZoneDisplaySwitch:UISwitch? + + @IBOutlet weak var colorSelectionPickerView:UIPickerView? + @IBOutlet weak var widthSelectionPickerView:UIPickerView? + @IBOutlet weak var alphaSelectionPickerView:UIPickerView? + @IBOutlet weak var visibleFlyZoneSelectionPickerView:UIPickerView? + + var colorPickerCurrentlySelectedRow: Int = 0 + var widthPickerCurrentlySelectedRow: Int = 0 + var alphaPickerCurrentlySelectedRow: Int = 0 + var visibleFlyZonesPickerCurrentlySelectedRow: Int = 0 + + @IBOutlet weak var replaceIconSegmentedView: UISegmentedControl! + @IBOutlet weak var replaceIconBlurView: UIVisualEffectView! + @IBOutlet weak var replaceIconImageView: UIImageView! + + override func viewDidLoad() { + super.viewDidLoad() + self.widthSlider?.minimumValue = 0.5 + self.widthSlider?.maximumValue = 10.0 + + self.mapWidget!.showDirectionToHome = true + self.replaceIconBlurView.layer.cornerRadius = 7.0 + self.replaceIconBlurView.layer.masksToBounds = true + self.mapWidget!.visibleFlyZones = [] + + self.mainStackView?.isLayoutMarginsRelativeArrangement = true + self.mainStackView?.directionalLayoutMargins = NSDirectionalEdgeInsets(top: 0, + leading: 10, + bottom: 0, + trailing: 10) + + if let selectedColorSelectionPickerViewRow = self.colorSelectionPickerView?.selectedRow(inComponent: 0) { + self.colorPickerCurrentlySelectedRow = selectedColorSelectionPickerViewRow + } + + if let selectedAlphaSelectionPickerViewRow = self.alphaSelectionPickerView?.selectedRow(inComponent: 0) { + self.alphaPickerCurrentlySelectedRow = selectedAlphaSelectionPickerViewRow + } + + if let selectedWidthSelectionPickerViewRow = self.widthSelectionPickerView?.selectedRow(inComponent: 0) { + self.widthPickerCurrentlySelectedRow = selectedWidthSelectionPickerViewRow + } + + if let selectedVisibleFlyZonesSelectionPickerViewRow = self.visibleFlyZoneSelectionPickerView?.selectedRow(inComponent: 0) { + self.visibleFlyZonesPickerCurrentlySelectedRow = selectedVisibleFlyZonesSelectionPickerViewRow + } + self.replaceIconImageView.image = #imageLiteral(resourceName: "Aircraft") + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.updateAlpha() + self.updateWidth() + self.updateFlyZones() + + if let mapWidget = self.mapWidget { + self.showLegendSwitch?.isOn = mapWidget.showFlyZoneLegend + } + } + + func updateAlpha() { + if self.alphaPickerCurrentlySelectedRow == 0 { + self.alphaSlider?.setValue(Float(self.mapWidget!.flyZoneOverlayAlpha(for: .restricted)), animated: false) + self.alphaLabel?.text = "\(self.mapWidget!.flyZoneOverlayAlpha(for: .restricted))" + } else if self.alphaPickerCurrentlySelectedRow == 1 { + self.alphaSlider?.setValue(Float(self.mapWidget!.flyZoneOverlayAlpha(for: .authorization)), animated: false) + self.alphaLabel?.text = "\(self.mapWidget!.flyZoneOverlayAlpha(for: .authorization))" + } else if self.alphaPickerCurrentlySelectedRow == 2 { + self.alphaSlider?.setValue(Float(self.mapWidget!.flyZoneOverlayAlpha(for: .enhancedWarning)), animated: false) + self.alphaLabel?.text = "\(self.mapWidget!.flyZoneOverlayAlpha(for: .enhancedWarning))" + } else if self.alphaPickerCurrentlySelectedRow == 3 { + self.alphaSlider?.setValue(Float(self.mapWidget!.flyZoneOverlayAlpha(for: .warning)), animated: false) + self.alphaLabel?.text = "\(self.mapWidget!.flyZoneOverlayAlpha(for: .warning))" + } else if self.alphaPickerCurrentlySelectedRow == 4 { + self.alphaSlider?.setValue(Float(self.mapWidget!.unlockedFlyZoneOverlayAlpha), animated: false) + self.alphaLabel?.text = "\(self.mapWidget!.unlockedFlyZoneOverlayAlpha)" + } else if self.alphaPickerCurrentlySelectedRow == 5 { + self.alphaSlider?.setValue(Float(self.mapWidget!.maximumHeightFlyZoneOverlayAlpha), animated: false) + self.alphaLabel?.text = "\(self.mapWidget!.maximumHeightFlyZoneOverlayAlpha)" + } else if self.alphaPickerCurrentlySelectedRow == 6 { + self.alphaSlider?.setValue(Float(self.mapWidget!.customUnlockFlyZoneOverlayAlpha), animated: false) + self.alphaLabel?.text = "\(self.mapWidget!.customUnlockFlyZoneOverlayAlpha)" + } else if self.alphaPickerCurrentlySelectedRow == 7 { + self.alphaSlider?.setValue(Float(self.mapWidget!.customUnlockFlyZoneSentToAircraftOverlayAlpha), animated: false) + self.alphaLabel?.text = "\(self.mapWidget!.customUnlockFlyZoneSentToAircraftOverlayAlpha)" + } else if self.alphaPickerCurrentlySelectedRow == 8 { + self.alphaSlider?.setValue(Float(self.mapWidget!.customUnlockFlyZoneEnabledOverlayAlpha), animated: false) + self.alphaLabel?.text = "\(self.mapWidget!.customUnlockFlyZoneEnabledOverlayAlpha)" + } + } + + func updateFlyZones() { + var visibleFlyZones:DUXBetaMapVisibleFlyZones = [] + + if self.visibleFlyZonesPickerCurrentlySelectedRow == 0 { + visibleFlyZones.insert(DUXBetaMapVisibleFlyZones.restricted) + } else if self.visibleFlyZonesPickerCurrentlySelectedRow == 1 { + visibleFlyZones.insert(DUXBetaMapVisibleFlyZones.authorization) + } else if self.visibleFlyZonesPickerCurrentlySelectedRow == 2 { + visibleFlyZones.insert(DUXBetaMapVisibleFlyZones.enhancedWarning) + } else if self.visibleFlyZonesPickerCurrentlySelectedRow == 3 { + visibleFlyZones.insert(DUXBetaMapVisibleFlyZones.warning) + } + + self.flyZoneDisplaySwitch?.setOn((self.mapWidget!.visibleFlyZones.contains(visibleFlyZones)), animated: true) + } + + func updateWidth() { + if self.widthPickerCurrentlySelectedRow == 0 { + self.widthSlider?.setValue(Float(self.mapWidget!.flyZoneOverlayBorderWidth), animated: false) + self.widthLabel?.text = "\(self.mapWidget!.flyZoneOverlayBorderWidth)" + } else if self.widthPickerCurrentlySelectedRow == 1 { + self.widthSlider?.setValue(Float(self.mapWidget!.flightPathStrokeWidth), animated: false) + self.widthLabel?.text = "\(self.mapWidget!.flightPathStrokeWidth)" + } else if self.widthPickerCurrentlySelectedRow == 2 { + self.widthSlider?.setValue(Float(self.mapWidget!.directionToHomeStrokeWidth), animated: false) + self.widthLabel?.text = "\(self.mapWidget!.directionToHomeStrokeWidth)" + } + } + + @IBAction func widthSliderControlChanged(sender: UISlider) { + let sliderValue = CGFloat(sender.value) + self.widthLabel?.text = "\(sliderValue)" + + if self.widthPickerCurrentlySelectedRow == 0 { + self.mapWidget!.flyZoneOverlayBorderWidth = sliderValue + } else if self.widthPickerCurrentlySelectedRow == 1 { + self.mapWidget!.flightPathStrokeWidth = sliderValue + } else if self.widthPickerCurrentlySelectedRow == 2 { + self.mapWidget!.directionToHomeStrokeWidth = sliderValue + } + } + + @IBAction func alphaSliderControlChanged(sender: UISlider) { + let sliderValue = CGFloat(sender.value) + self.alphaLabel?.text = "\(sliderValue)" + + if self.alphaPickerCurrentlySelectedRow == 0 { + self.mapWidget!.setFlyZoneOverlayAlpha(sliderValue, for: .restricted) + } else if self.alphaPickerCurrentlySelectedRow == 1 { + self.mapWidget!.setFlyZoneOverlayAlpha(sliderValue, for: .authorization) + } else if self.alphaPickerCurrentlySelectedRow == 2 { + self.mapWidget!.setFlyZoneOverlayAlpha(sliderValue, for: .enhancedWarning) + } else if self.alphaPickerCurrentlySelectedRow == 3 { + self.mapWidget!.setFlyZoneOverlayAlpha(sliderValue, for: .warning) + } else if self.alphaPickerCurrentlySelectedRow == 4 { + self.mapWidget!.unlockedFlyZoneOverlayAlpha = sliderValue + } else if self.alphaPickerCurrentlySelectedRow == 5 { + self.mapWidget!.maximumHeightFlyZoneOverlayAlpha = sliderValue + } else if self.alphaPickerCurrentlySelectedRow == 6 { + self.mapWidget!.customUnlockFlyZoneOverlayAlpha = sliderValue + } else if self.alphaPickerCurrentlySelectedRow == 7 { + self.mapWidget!.customUnlockFlyZoneSentToAircraftOverlayAlpha = sliderValue + } else if self.alphaPickerCurrentlySelectedRow == 8 { + self.mapWidget!.customUnlockFlyZoneEnabledOverlayAlpha = sliderValue + } + } + + @IBAction func flyZoneDisplaySwitchValueChanged(sender: UISwitch) { + let isOn = sender.isOn + var visibleFlyZones:DUXBetaMapVisibleFlyZones = [] + + if self.visibleFlyZonesPickerCurrentlySelectedRow == 0 { + visibleFlyZones.insert(DUXBetaMapVisibleFlyZones.restricted) + } else if self.visibleFlyZonesPickerCurrentlySelectedRow == 1 { + visibleFlyZones.insert(DUXBetaMapVisibleFlyZones.authorization) + } else if self.visibleFlyZonesPickerCurrentlySelectedRow == 2 { + visibleFlyZones.insert(DUXBetaMapVisibleFlyZones.enhancedWarning) + } else if self.visibleFlyZonesPickerCurrentlySelectedRow == 3 { + visibleFlyZones.insert(DUXBetaMapVisibleFlyZones.warning) + } + + if isOn { + self.mapWidget!.visibleFlyZones.insert(visibleFlyZones) + } else { + self.mapWidget!.visibleFlyZones.remove(visibleFlyZones) + } + + self.updateFlyZones() + } + + func updateMapWith(color:UIColor) { + if colorPickerCurrentlySelectedRow == 0 { + self.mapWidget!.setFlyZoneOverlayColor(color, for: .restricted) + } else if colorPickerCurrentlySelectedRow == 1 { + self.mapWidget!.setFlyZoneOverlayColor(color, for: .authorization) + } else if colorPickerCurrentlySelectedRow == 2 { + self.mapWidget!.setFlyZoneOverlayColor(color, for: .enhancedWarning) + } else if colorPickerCurrentlySelectedRow == 3 { + self.mapWidget!.setFlyZoneOverlayColor(color, for: .warning) + } else if colorPickerCurrentlySelectedRow == 4 { + self.mapWidget!.unlockedFlyZoneOverlayColor = color + } else if colorPickerCurrentlySelectedRow == 5 { + self.mapWidget!.maximumHeightFlyZoneOverlayColor = color + } else if colorPickerCurrentlySelectedRow == 6 { + self.mapWidget!.flightPathStrokeColor = color + } else if colorPickerCurrentlySelectedRow == 7 { + self.mapWidget!.directionToHomeStrokeColor = color + } else if colorPickerCurrentlySelectedRow == 8 { + self.mapWidget!.customUnlockFlyZoneOverlayColor = color + } else if self.colorPickerCurrentlySelectedRow == 9 { + self.mapWidget!.customUnlockFlyZoneSentToAircraftOverlayColor = color + } else if self.colorPickerCurrentlySelectedRow == 10 { + self.mapWidget!.customUnlockFlyZoneEnabledOverlayColor = color + } + } + + @IBAction func close(_ sender: UIButton) { + self.willMove(toParent: nil) + self.view.removeFromSuperview() + self.removeFromParent() + } + + //MARK - FCColorPickerViewControllerDelegate + + func colorPickerViewController(_ colorPicker: FCColorPickerViewController, didSelect color: UIColor) { + self.updateMapWith(color: color) + self.presentedViewController?.dismiss(animated: true, completion: nil) + } + + func colorPickerViewControllerDidCancel(_ colorPicker: FCColorPickerViewController) { + self.presentedViewController?.dismiss(animated: true, completion: nil) + } + + func currentlySelectedColorFor(row:Int) -> UIColor? { + if colorPickerCurrentlySelectedRow == 0 { + return self.mapWidget!.flyZoneOverlayColor(for: .restricted) + } else if colorPickerCurrentlySelectedRow == 1 { + return self.mapWidget!.flyZoneOverlayColor(for: .authorization) + } else if colorPickerCurrentlySelectedRow == 2 { + return self.mapWidget!.flyZoneOverlayColor(for: .enhancedWarning) + } else if colorPickerCurrentlySelectedRow == 3 { + return self.mapWidget!.flyZoneOverlayColor(for: .warning) + } else if colorPickerCurrentlySelectedRow == 4 { + return self.mapWidget!.unlockedFlyZoneOverlayColor + } else if colorPickerCurrentlySelectedRow == 5 { + return self.mapWidget!.maximumHeightFlyZoneOverlayColor + } else if colorPickerCurrentlySelectedRow == 6 { + return self.mapWidget!.flightPathStrokeColor + } else if colorPickerCurrentlySelectedRow == 7 { + return self.mapWidget!.directionToHomeStrokeColor + } else if colorPickerCurrentlySelectedRow == 8 { + return self.mapWidget!.customUnlockFlyZoneOverlayColor + } else if self.colorPickerCurrentlySelectedRow == 9 { + return self.mapWidget!.customUnlockFlyZoneSentToAircraftOverlayColor + } else if self.colorPickerCurrentlySelectedRow == 10 { + return self.mapWidget!.customUnlockFlyZoneEnabledOverlayColor + } else { + return nil + } + } + + @IBAction func toggleColor() { + if let currentlySelectedColorForPickerTarget = self.currentlySelectedColorFor(row:self.colorPickerCurrentlySelectedRow) { + let colorPicker = FCColorPickerViewController.colorPicker(with: currentlySelectedColorForPickerTarget, delegate: self) + self.present(colorPicker, animated: true, completion: nil) + } else { + self.updateMapWith(color: UIColor.cyan) + } + } + + @IBAction func directionToHomeValueChanged(_ sender: UISwitch) { + self.mapWidget!.showDirectionToHome = sender.isOn + } + + @IBAction func lockAircraftCameraValueChanged(_ sender: UISwitch) { + self.mapWidget!.isMapCameraLockedOnAircraft = sender.isOn + if (sender.isOn) { + self.lockHomeCameraSwitch?.setOn(false, animated: true) + } + } + + @IBAction func lockHomePointCameraValueChanged(_ sender: UISwitch) { + self.mapWidget!.isMapCameraLockedOnHomePoint = sender.isOn + if (sender.isOn) { + self.lockAircraftCameraSwitch?.setOn(false, animated: true) + } + } + + @IBAction func showFlightPathValueChanged(_ sender: UISwitch) { + self.mapWidget!.showFlightPath = sender.isOn + } + + @IBAction func showHomePointValueChanged(_ sender: UISwitch) { + self.mapWidget!.showHomeAnnotation = sender.isOn + } + + @IBAction func tapToUnlockEnabledValueChanged(_ sender: UISwitch) { + self.mapWidget!.tapToUnlockEnabled = sender.isOn + } + + @IBAction func showLegendValueChanged(_ sender: UISwitch) { + self.mapWidget!.showFlyZoneLegend = sender.isOn + } + + @IBAction func showCustomUnlockZonesValueChanged(_ sender: UISwitch) { + self.mapWidget!.showCustomUnlockZones = sender.isOn + } + + @IBAction func showDJIAccountLoginIndicator(_ sender: UISwitch) { + self.mapWidget!.showDJIAccountLoginIndicator = sender.isOn + } + + @IBAction func replaceIconButtonPressed(_ sender: UIButton) { + if self.replaceIconSegmentedView.selectedSegmentIndex == 0 { + self.mapWidget!.changeAnnotation(of: .aircraft, toCustomImage: self.replaceIconImageView.image!, withCenterOffset: CGPoint(x: -8.75, y: -27.3)); + } else if self.replaceIconSegmentedView.selectedSegmentIndex == 1 { + self.mapWidget!.changeAnnotation(of: .home, toCustomImage: self.replaceIconImageView.image!, withCenterOffset: CGPoint(x: -8, y: -15)); + } else if self.replaceIconSegmentedView.selectedSegmentIndex == 2 { + self.mapWidget!.changeAnnotation(of: .eligibleFlyZones, toCustomImage: self.replaceIconImageView.image!, withCenterOffset: CGPoint(x: 8, y: -15)); + } else if self.replaceIconSegmentedView.selectedSegmentIndex == 3 { + self.mapWidget!.changeAnnotation(of: .unlockedFlyZones, toCustomImage: self.replaceIconImageView.image!, withCenterOffset: CGPoint(x: 8, y: -15)); + } else if self.replaceIconSegmentedView.selectedSegmentIndex == 4 { + self.mapWidget!.changeAnnotation(of: .customUnlockedFlyZones, toCustomImage: self.replaceIconImageView.image!, withCenterOffset: CGPoint(x: 8, y: -15)); + } + } + + @IBAction func replaceIconValueChanged(_ sender: UISegmentedControl) { + if sender.selectedSegmentIndex == 0 { + self.replaceIconImageView.image = #imageLiteral(resourceName: "Aircraft") + } else { + self.replaceIconImageView.image = #imageLiteral(resourceName: "HomePoint") + } + } + + //MARK: - UIPickerViewDataSource + + func numberOfComponents(in pickerView: UIPickerView) -> Int { + return 1 + } + + func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { + if pickerView == self.colorSelectionPickerView { + return 11 + } else if pickerView == self.widthSelectionPickerView { + return 3 + } else if pickerView == self.alphaSelectionPickerView { + return 9 + } else if pickerView == self.visibleFlyZoneSelectionPickerView { + return 4 + } else { + return 0 + } + } + + //MARK: - UIPickerViewDelegate + + public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { + if pickerView == self.colorSelectionPickerView { + return self.colorSelectionTitleForRow(row: row, forComponent: component) + } else if pickerView == self.widthSelectionPickerView { + return self.widthSelectionTitleForRow(row: row, forComponent: component) + } else if pickerView == self.alphaSelectionPickerView { + return self.alphaSelectionTitleForRow(row: row, forComponent: component) + } else if pickerView == self.visibleFlyZoneSelectionPickerView { + return self.visibleFlyZoneSelectionTitleForRow(row: row, forComponent: component) + } else { + return nil + } + } + + func colorSelectionTitleForRow(row: Int, forComponent component:Int) -> String? { + if row == 0 { + return "Restricted Overlay Color" + } else if row == 1 { + return "Authorization Overlay Color" + } else if row == 2 { + return "Enhanced Warning Overlay Color" + } else if row == 3 { + return "Warning Overlay Color" + } else if row == 4 { + return "Self Unlocked Overlay Color" + } else if row == 5 { + return "Max Height Overlay Color" + } else if row == 6 { + return "Flight Path Color" + } else if row == 7 { + return "Direction to Home Color" + } else if row == 8 { + return "Custom Unlock Not Sent Not Enabled Color" + } else if row == 9 { + return "Custom Unlock Sent Not Enabled Color" + } else if row == 10 { + return "Custom Unlock Sent Enabled Color" + } else { + return "" + } + } + + func widthSelectionTitleForRow(row: Int, forComponent component:Int) -> String? { + if row == 0 { + return "Overlay Border Width" + } else if row == 1 { + return "Flight Path Stroke Width" + } else if row == 2 { + return "Direction to Home Stroke Width" + } else { + return "" + } + } + + func alphaSelectionTitleForRow(row: Int, forComponent component:Int) -> String? { + if row == 0 { + return "Restricted Overlay Alpha" + } else if row == 1 { + return "Authorization Overlay Alpha" + } else if row == 2 { + return "Enhanced Warning Overlay Alpha" + } else if row == 3 { + return "Warning Overlay Alpha" + } else if row == 4 { + return "Self Unlocked Overlay Alpha" + } else if row == 5 { + return "Max Height Overlay Alpha" + } else if row == 6 { + return "Custom Unlock Not Sent Not Enabled Alpha" + } else if row == 7 { + return "Custom Unlock Sent Not Enabled Alpha" + } else if row == 8 { + return "Custom Unlock Sent Enabled Alpha" + } else { + return "" + } + } + + func visibleFlyZoneSelectionTitleForRow(row: Int, forComponent component:Int) -> String? { + if row == 0 { + return "Restricted" + } else if row == 1 { + return "Authorization" + } else if row == 2 { + return "Enhanced Warning" + } else if row == 3 { + return "Warning" + } else { + return "" + } + } + + public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { + if pickerView == self.colorSelectionPickerView { + self.didSelectColor(row: row, inComponent: component) + } else if pickerView == self.widthSelectionPickerView { + self.didSelectAlpha(row: row, inComponent: component) + } else if pickerView == self.alphaSelectionPickerView { + self.didSelectWidth(row: row, inComponent: component) + } else if pickerView == self.visibleFlyZoneSelectionPickerView { + self.didSelectVisibleFlyZone(row: row, inComponent: component) + } + } + + func didSelectColor(row: Int, inComponent component: Int) { + self.colorPickerCurrentlySelectedRow = row + } + + func didSelectWidth(row: Int, inComponent component: Int) { + self.widthPickerCurrentlySelectedRow = row + self.updateWidth() + } + + func didSelectAlpha(row: Int, inComponent component: Int) { + self.alphaPickerCurrentlySelectedRow = row + self.updateAlpha() + } + + func didSelectVisibleFlyZone(row: Int, inComponent component: Int) { + self.visibleFlyZonesPickerCurrentlySelectedRow = row + self.updateFlyZones() + } +} + diff --git a/UXSDKBetaSample/UXSDKBetaSample/Helpers.swift b/UXSDKBetaSample/UXSDKBetaSample/Helpers.swift new file mode 100644 index 0000000..e2b8250 --- /dev/null +++ b/UXSDKBetaSample/UXSDKBetaSample/Helpers.swift @@ -0,0 +1,73 @@ +// +// WidgetsListViewController.swift +// DJIUXSDK +// +// Copyright © 2018-2019 DJI +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +import UIKit + +extension UIControl { + func connect(controlAction:ControlAction, for event:UIControl.Event) { + self.addTarget(controlAction, + action: #selector(ControlAction.performAction(_:)), + for: event) + } + + func connect(controlAction:ControlAction, for events:[UIControl.Event]) { + for event in events { + self.addTarget(controlAction, + action: #selector(ControlAction.performAction(_:)), + for: event) + } + } + + func connect(action: @escaping ControlActionClosure, for event:UIControl.Event) -> ControlAction { + let controlAction = ControlAction(action) + + self.connect(controlAction: controlAction, + for: event) + + return controlAction + } + + func connect(action: @escaping ControlActionClosure, for events:[UIControl.Event]) -> ControlAction { + let controlAction = ControlAction(action) + + self.connect(controlAction: controlAction, + for: events) + + return controlAction + } +} + +typealias ControlActionClosure = () -> Void + +public final class ControlAction { + let action: ControlActionClosure + init(_ action: @escaping ControlActionClosure) { + self.action = action + } + + @objc func performAction(_ sender:Any) { + action() + } +} diff --git a/UXSDKBetaSample/UXSDKBetaSample/Info.plist b/UXSDKBetaSample/UXSDKBetaSample/Info.plist index fd0866d..2f89e95 100644 --- a/UXSDKBetaSample/UXSDKBetaSample/Info.plist +++ b/UXSDKBetaSample/UXSDKBetaSample/Info.plist @@ -21,9 +21,11 @@ CFBundleVersion 1 DJISDKAppKey - Insert your DJI SDK app key here + Replace_With_Your_DJI_App_Key LSRequiresIPhoneOS + NSBluetoothAlwaysUsageDescription + Bluetooth Use is Required for Mobile SDK Osmo Support NSLocationAlwaysAndWhenInUseUsageDescription Location Use is Required for Map Functionality NSLocationWhenInUseUsageDescription diff --git a/UXSDKBetaSample/UXSDKBetaSample/MainViewController.swift b/UXSDKBetaSample/UXSDKBetaSample/MainViewController.swift index ed73c75..ef4e3c6 100644 --- a/UXSDKBetaSample/UXSDKBetaSample/MainViewController.swift +++ b/UXSDKBetaSample/UXSDKBetaSample/MainViewController.swift @@ -44,7 +44,7 @@ class MainViewController: UIViewController, UITextFieldDelegate, LogCenterListen override func viewDidLoad() { super.viewDidLoad() - NotificationCenter.default.addObserver(self, selector: #selector(productCommunicationDidChange), name: Notification.Name(rawValue: "ProductCommunicationManagerStateDidChange"), object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(productCommunicationDidChange), name: Notification.Name(rawValue: "ProductCommunicationServiceStateDidChange"), object: nil) self.bridgeIDField.delegate = self LogCenter.default.add(listener: self) } @@ -52,21 +52,21 @@ class MainViewController: UIViewController, UITextFieldDelegate, LogCenterListen override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.version.text = "\(DUXBetaSDKAttributes.sdkVersion())-\(DUXBetaSDKAttributes.sdkBuildNumber())" - self.bridgeIDField.text = self.appDelegate.productCommManager.bridgeAppIP - self.useBridgeSwitch.isOn = self.appDelegate.productCommManager.useBridge + self.bridgeIDField.text = ProductCommunicationService.shared.bridgeAppIP + self.useBridgeSwitch.isOn = ProductCommunicationService.shared.useBridge } @IBAction func registerAction() { - self.appDelegate.productCommManager.registerWithProduct() + ProductCommunicationService.shared.registerWithProduct() } @IBAction func connectAction() { - self.appDelegate.productCommManager.connectToProduct() + ProductCommunicationService.shared.connectToProduct() } @IBAction func useBridgeAction(_ sender: UISwitch) { - self.appDelegate.productCommManager.useBridge = sender.isOn - self.appDelegate.productCommManager.disconnectProduct() + ProductCommunicationService.shared.useBridge = sender.isOn + ProductCommunicationService.shared.productDisconnected() } @IBAction func pushWidgetList() { @@ -86,7 +86,7 @@ class MainViewController: UIViewController, UITextFieldDelegate, LogCenterListen } @objc func productCommunicationDidChange() { - if self.appDelegate.productCommManager.registered { + if ProductCommunicationService.shared.registered { self.registered.text = "YES" self.register.isHidden = true } else { @@ -94,7 +94,7 @@ class MainViewController: UIViewController, UITextFieldDelegate, LogCenterListen self.register.isHidden = false } - if self.appDelegate.productCommManager.connected { + if ProductCommunicationService.shared.connected { self.connected.text = "YES" self.connect.isHidden = true @@ -132,7 +132,7 @@ class MainViewController: UIViewController, UITextFieldDelegate, LogCenterListen func textFieldDidEndEditing(_ textField: UITextField) { if textField == self.bridgeIDField { - self.appDelegate.productCommManager.bridgeAppIP = textField.text! + ProductCommunicationService.shared.bridgeAppIP = textField.text! } } diff --git a/UXSDKBetaSample/UXSDKBetaSample/Services/ProductCommunicationService.swift b/UXSDKBetaSample/UXSDKBetaSample/Services/ProductCommunicationService.swift new file mode 100644 index 0000000..5579712 --- /dev/null +++ b/UXSDKBetaSample/UXSDKBetaSample/Services/ProductCommunicationService.swift @@ -0,0 +1,283 @@ +// +// ProductCommunicationService.swift +// DJIUXSDK +// +// Copyright © 2018-2019 DJI +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// + +import UIKit +import DJISDK + +// +// ProductCommunicationService.swift +// UXSDK Sample +// +// Copyright © 2016 DJI. All rights reserved. +// + +import UIKit +import DJISDK + +let ProductCommunicationServiceStateDidChange = "ProductCommunicationServiceStateDidChange" + +// Automatically set default to bridge when on iOS simulator +func defaultUseBridgeSetting() -> Bool { + #if arch(i386) || arch(x86_64) + return true + #else + return false + #endif +} + +func postNotificationNamed(_ rawStringName:String, + dispatchOntoMainQueue:Bool = false, + notificationCenter:NotificationCenter = NotificationCenter.default) { + let post = { + notificationCenter.post(Notification(name: Notification.Name(rawValue: rawStringName))) + } + + if dispatchOntoMainQueue { + DispatchQueue.main.async { + post() + } + } else { + post() + } +} + +public let FligntControllerSimulatorDidStart = "FligntControllerSimulatorDidStart" +public let FligntControllerSimulatorDidStop = "FligntControllerSimulatorDidStop" + +class SimulatorControl: NSObject { + var isSimulatorActive:Bool = false { + didSet { + if self.isSimulatorActive { + postNotificationNamed(FligntControllerSimulatorDidStart, dispatchOntoMainQueue: true) + } else { + postNotificationNamed(FligntControllerSimulatorDidStop, dispatchOntoMainQueue: true) + } + } + } + + func startListeningOnProductState() { + let isSimulatorActiveKey = DJIFlightControllerKey(param: DJIFlightControllerParamIsSimulatorActive)! + + if let active = DJISDKManager.keyManager()?.getValueFor(isSimulatorActiveKey)?.boolValue { + self.isSimulatorActive = active + } + + DJISDKManager.keyManager()?.startListeningForChanges(on: isSimulatorActiveKey, + withListener: self, + andUpdate: { (updatedValue:DJIKeyedValue?, priorValue:DJIKeyedValue?) in + if let isSimulatorActive = updatedValue?.boolValue { + self.isSimulatorActive = isSimulatorActive + } + }) + + DJISDKManager.keyManager()?.getValueFor(isSimulatorActiveKey, + withCompletion: { (updatedValue:DJIKeyedValue?, error:Error?) in + if let isSimulatorActive = updatedValue?.boolValue { + self.isSimulatorActive = isSimulatorActive + } + }) + } + + func stopListeningOnProductState() { + let isSimulatorActiveKey = DJIFlightControllerKey(param: DJIFlightControllerParamIsSimulatorActive)! + + DJISDKManager.keyManager()?.stopListening(on: isSimulatorActiveKey, + ofListener: self) + } + + deinit { + self.stopListeningOnProductState() + } + + // Returns false if no aircraft present, true if simulator command sent + func startSimulator(at locationCoordinates:CLLocationCoordinate2D) -> Bool { + guard let aircraft = DJISDKManager.product() as? DJIAircraft else { + return false + } + + guard let simulator = aircraft.flightController?.simulator else { + return false + } + + simulator.start(withLocation: locationCoordinates, + updateFrequency: 20, + gpsSatellitesNumber: 12) { (error:Error?) in + if let e = error { + print("Start Simulator Error: \(e)") + } else { + print("Start Simulator Command Acked") + } + } + + return true + } + + func stopSimulator() -> Bool { + guard let stopSimulatorKey = DJIFlightControllerKey(param: DJIFlightControllerParamStopSimulator) else { + return false + } + + guard let keyManager = DJISDKManager.keyManager() else { + return false + } + + keyManager.performAction(for: stopSimulatorKey, + withArguments: nil, + andCompletion: { (didSucceed:Bool, value:DJIKeyedValue?, error:Error?) in + if let e = error { + print("Stop Simulator Error: \(e)") + } else { + print("Stop Simulator Command Acked") + } + }) + + return true + } +} + +// Returns "0.0.0.0" if no cached value present +func fetchCachedBridgeAppIP() -> String { + if let ip = UserDefaults.standard.value(forKey: "bridgeAppIP") as? String { + return ip + } else { + return "0.0.0.0" + } +} + +@dynamicMemberLookup +class ProductCommunicationService: NSObject, DJISDKManagerDelegate { + // Static Instance + static let shared = ProductCommunicationService() + + open weak var appDelegate = UIApplication.shared.delegate as? AppDelegate + open var connectedProduct: DJIBaseProduct! + + var registered = false + var connected = false + + var bridgeAppIP = fetchCachedBridgeAppIP() { + didSet { + UserDefaults.standard.set(bridgeAppIP, forKey: "bridgeAppIP") + } + } + var useBridge = defaultUseBridgeSetting() { + didSet { + if useBridge == false { + NSLog("Disabling bridge mode...") + DJISDKManager.disableBridgeMode() + } else { + NSLog("Enabling bridge mode with IP \(self.bridgeAppIP)...") + DJISDKManager.enableBridgeMode(withBridgeAppIP: self.bridgeAppIP) + } + } + } + + //MARK: - Start Registration + func registerWithProduct() { + guard + let path = Bundle.main.path(forResource: "Info", ofType: "plist"), + let dict = NSDictionary(contentsOfFile: path) as? Dictionary, + let appKey = dict["DJISDKAppKey"] as? String, + appKey != "PASTE_YOUR_DJI_APP_KEY_HERE" + else { + print("\n<<>>\n") + return + } + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + NSLog("Registering Product with registration ID: \(appKey)") + DJISDKManager.registerApp(with: self) + } + } + + //MARK: - Start Connecting to Product + open func connectToProduct() { + if self.useBridge { + NSLog("Connecting to Product using debug IP address: \(bridgeAppIP)...") + DJISDKManager.enableBridgeMode(withBridgeAppIP: bridgeAppIP) + } else { + NSLog("Connecting to product...") + let startedResult = DJISDKManager.startConnectionToProduct() + + if startedResult { + NSLog("Connecting to product started successfully!") + } else { + NSLog("Connecting to product failed to start!") + } + } + } + + //MARK: - DJISDKManagerDelegate + func appRegisteredWithError(_ error: Error?) { + if error == nil { + self.registered = true + postNotificationNamed(ProductCommunicationServiceStateDidChange, dispatchOntoMainQueue: true) + self.simulatorControl.startListeningOnProductState() + self.connectToProduct() + } else { + NSLog("Error Registrating App: \(String(describing: error))") + } + } + + func didUpdateDatabaseDownloadProgress(_ progress: Progress) { + print("Downloading Database Progress: \(progress.completedUnitCount) / \(progress.totalUnitCount)") + } + + func productConnected(_ product: DJIBaseProduct?) { + if product != nil { + self.connected = true + NotificationCenter.default.post(Notification(name: Notification.Name(rawValue: ProductCommunicationServiceStateDidChange))) + NSLog("Connection to new product succeeded!") + self.connectedProduct = product + } + } + + func productDisconnected() { + DJISDKManager.stopConnectionToProduct() + + self.connected = false + NotificationCenter.default.post(Notification(name: Notification.Name(rawValue: ProductCommunicationServiceStateDidChange))) + NSLog("Disconnected from product!"); + } + + //MARK: - Bridge Mode API + + //MARK: - Simulator Controls API + let simulatorControl:SimulatorControl = SimulatorControl() + + // Leverages Swift language feature described in SE-0252 + subscript(dynamicMember keyPath: KeyPath) -> Bool { + return simulatorControl[keyPath: keyPath] + } + + // Returns false if no aircraft present, true if simulator command sent + func stopSimulator() -> Bool { + return self.simulatorControl.stopSimulator() + } + + // Returns false if no aircraft present, true if simulator command sent + func startSimulator(at locationCoordinates:CLLocationCoordinate2D) -> Bool { + return self.simulatorControl.startSimulator(at: locationCoordinates) + } +} diff --git a/UXSDKBetaSample/UXSDKBetaSample/SingleWidgetViewController.swift b/UXSDKBetaSample/UXSDKBetaSample/SingleWidgetViewController.swift index 7f85f7b..ccd3d4c 100644 --- a/UXSDKBetaSample/UXSDKBetaSample/SingleWidgetViewController.swift +++ b/UXSDKBetaSample/UXSDKBetaSample/SingleWidgetViewController.swift @@ -26,6 +26,25 @@ import UIKit import DJIUXSDKBeta +extension UIColor { + static func borderColorPalette() -> [UIColor] { + return [UIColor.red, + UIColor.green, + UIColor.blue, + UIColor.orange, + UIColor.yellow, + UIColor.magenta, + UIColor.cyan, + UIColor.purple, + UIColor.brown] + } + + static func borderColor(for level:Int) -> UIColor { + let palette = self.borderColorPalette() + return palette[level % palette.count] + } +} + class SingleWidgetViewController: UIViewController { @IBOutlet var noWidgetSelectedLabel: UILabel! @@ -34,43 +53,45 @@ class SingleWidgetViewController: UIViewController { @IBOutlet var aspectRatioLabel: UILabel! @IBOutlet var currentSizeLabel: UILabel! @IBOutlet var widgetDescriptionLabel: UILabel! + var showCustomizationViewButton: UIButton? private var pinchStartHeight: CGFloat = 0.0 private var heightConstraint: NSLayoutConstraint? + private var additionalControlsView: UIView? + + private var doubleSizeControlAction: ControlAction? + private var showCustomizationViewAction: ControlAction? + + internal var shouldShowCustomizationView: Bool = false - private var _widget: DUXBetaBaseWidget? = nil + // MARK: Widget Setup / Teardown var widget: DUXBetaBaseWidget? { - set { + willSet { // Cleanup old widget from parent self.tearDownCurrentWidget() - - _widget = newValue - if let nonNilWidget = _widget { + } + + didSet { + if let nonNilWidget = self.widget { self.setupViewHierarchyFor(widget: nonNilWidget) } else { self.setupEmptyViewHierarchy() } } - get { return _widget } - } - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - if let widget = self.widget { - currentSizeLabel.text = String(format: "[%.1f, %.1f]", widget.view.frame.size.width, widget.view.frame.size.height) - } } public func tearDownCurrentWidget() { - _widget?.removeFromParent() - _widget?.view.removeFromSuperview() + self.widget?.removeFromParent() + self.widget?.view.removeFromSuperview() } public func setupViewHierarchyFor(widget:DUXBetaBaseWidget) { self.noWidgetSelectedLabel.isHidden = true self.infoView.isHidden = false + self.additionalControlsView?.isHidden = false self.pinchToResizeLabel.isHidden = false - + self.showCustomizationViewButton?.isHidden = !self.shouldShowCustomizationView + widget.install(in: self) self.configureConstraints() self.recursivelySetBorderForView(view: widget.view, borderEnabled: true, level: 0) @@ -82,11 +103,100 @@ class SingleWidgetViewController: UIViewController { public func setupEmptyViewHierarchy() { self.noWidgetSelectedLabel.isHidden = false self.infoView.isHidden = true + self.additionalControlsView?.isHidden = true self.pinchToResizeLabel.isHidden = true self.aspectRatioLabel.text = "1.0" self.currentSizeLabel.text = "[40.0, 40.0]" } + // MARK: View Lifecycle + + override func viewDidLoad() { + super.viewDidLoad() + self.configureControlViews() + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + if let widget = self.widget { + currentSizeLabel.text = String(format: "[%.1f, %.1f]", widget.view.frame.size.width, widget.view.frame.size.height) + } + self.view.bringSubviewToFront(self.infoView) + self.view.bringSubviewToFront(self.pinchToResizeLabel) + if let v = self.additionalControlsView { + self.view.bringSubviewToFront(v) + } + } + + // MARK: Construct View and Constraint Hierarchy + + func configureControlViews() { + let doubleSizeButton = UIButton(type: .system) + doubleSizeButton.translatesAutoresizingMaskIntoConstraints = false + doubleSizeButton.setTitle("Double Size", + for: .normal) + doubleSizeButton.heightAnchor.constraint(greaterThanOrEqualToConstant: 25.0).isActive = true + self.doubleSizeControlAction = doubleSizeButton.connect(action: { + if let hc = self.heightConstraint { + hc.constant = hc.constant * 2 + self.view.setNeedsLayout() + } + }, for: .touchUpInside) + + let showCustomizationViewButton = UIButton(type: .system) + showCustomizationViewButton.translatesAutoresizingMaskIntoConstraints = false + showCustomizationViewButton.setTitle("Show Customization", + for: .normal) + showCustomizationViewButton.heightAnchor.constraint(greaterThanOrEqualToConstant: 25.0).isActive = true + self.showCustomizationViewAction = showCustomizationViewButton.connect(action: { + self.showMapCustomizationView() + }, for: .touchUpInside) + self.showCustomizationViewButton = showCustomizationViewButton + + let subviews:[UIView] = [doubleSizeButton, showCustomizationViewButton] + let stackview = UIStackView(arrangedSubviews: subviews) + stackview.translatesAutoresizingMaskIntoConstraints = false + stackview.axis = .vertical + stackview.distribution = .equalSpacing + stackview.spacing = UIStackView.spacingUseSystem + stackview.isLayoutMarginsRelativeArrangement = true + stackview.directionalLayoutMargins = NSDirectionalEdgeInsets(top: 5, + leading: 5, + bottom: 5, + trailing: 5) + + let additionalControlsView = UIView() + additionalControlsView.translatesAutoresizingMaskIntoConstraints = false + additionalControlsView.addSubview(stackview) + + let effect = UIBlurEffect(style: .regular) + let effectView = UIVisualEffectView(effect: effect) + effectView.translatesAutoresizingMaskIntoConstraints = false + additionalControlsView.addSubview(effectView) + additionalControlsView.sendSubviewToBack(effectView) + additionalControlsView.addConstraints([ + effectView.leadingAnchor.constraint(equalTo: additionalControlsView.leadingAnchor), + effectView.trailingAnchor.constraint(equalTo: additionalControlsView.trailingAnchor), + effectView.topAnchor.constraint(equalTo: additionalControlsView.topAnchor), + effectView.bottomAnchor.constraint(equalTo: additionalControlsView.bottomAnchor), + ]) + + stackview.leadingAnchor.constraint(equalTo: additionalControlsView.leadingAnchor).isActive = true + stackview.trailingAnchor.constraint(equalTo: additionalControlsView.trailingAnchor).isActive = true + stackview.topAnchor.constraint(equalTo: additionalControlsView.topAnchor).isActive = true + stackview.bottomAnchor.constraint(equalTo: additionalControlsView.bottomAnchor).isActive = true + + self.view.addSubview(additionalControlsView) + self.view.addConstraints([ + self.view.safeAreaLayoutGuide.topAnchor.constraint(equalTo: additionalControlsView.topAnchor, constant: 10.0), + self.infoView.trailingAnchor.constraint(equalTo: additionalControlsView.leadingAnchor, constant: -8.0) + ]) + + self.additionalControlsView = additionalControlsView + + self.setupEmptyViewHierarchy() + } + func configureConstraints () { if let widget = self.widget { @@ -128,11 +238,34 @@ class SingleWidgetViewController: UIViewController { } } + // MARK: Widget Customization View + + func showMapCustomizationView() { + if let mapWidget = self.widget as? DUXBetaMapWidget { + let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: type(of: self))) + let mapCustomizationViewController = storyboard.instantiateViewController(withIdentifier: "CustomMapViewController") as! CustomMapViewController + mapCustomizationViewController.mapWidget = mapWidget + + self.addChild(mapCustomizationViewController) + self.view.addSubview(mapCustomizationViewController.view) + mapCustomizationViewController.didMove(toParent: self) + + mapCustomizationViewController.view.translatesAutoresizingMaskIntoConstraints = false + mapCustomizationViewController.view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0).isActive = true + mapCustomizationViewController.view.topAnchor.constraint(equalTo: self.widgetDescriptionLabel.bottomAnchor, constant: 16.0).isActive = true + mapCustomizationViewController.view.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true + mapCustomizationViewController.view.widthAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.widthAnchor, multiplier: 1.0/3.0).isActive = true + mapCustomizationViewController.view.setNeedsLayout() + mapCustomizationViewController.view.layoutIfNeeded() + } + } + + // MARK: User Interaction Handlers + @IBAction func handlePinch(recognizer: UIPinchGestureRecognizer) { if let hc = self.heightConstraint { if (recognizer.state == .began) { self.pinchStartHeight = hc.constant - print("Pinch Zoom Height: \(hc.constant)") } hc.constant = self.pinchStartHeight * recognizer.scale self.view.setNeedsLayout() @@ -140,23 +273,15 @@ class SingleWidgetViewController: UIViewController { } @IBAction func doubleTap(recognizer: UITapGestureRecognizer) { - if let nonNilWidget = _widget { + if let nonNilWidget = self.widget { let borderEnabled = nonNilWidget.view.layer.borderWidth == 0 self.recursivelySetBorderForView(view: nonNilWidget.view, borderEnabled: borderEnabled, level: 0) } } - private let colors: [UIColor] = [UIColor.red, - UIColor.green, - UIColor.blue, - UIColor.orange, - UIColor.yellow, - UIColor.magenta, - UIColor.cyan, - UIColor.purple, - UIColor.brown] + func recursivelySetBorderForView(view: UIView, borderEnabled: Bool, level: Int) { if (borderEnabled) { - view.layer.borderColor = colors[level % colors.count].cgColor + view.layer.borderColor = UIColor.borderColor(for: level).cgColor view.layer.borderWidth = 1 } else { view.layer.borderColor = UIColor.clear.cgColor @@ -166,22 +291,11 @@ class SingleWidgetViewController: UIViewController { self.recursivelySetBorderForView(view: subView, borderEnabled: borderEnabled, level: level + 1) } } - - func closeButtonPressed(for widget: DUXBetaBaseWidget!) { - self.widget?.removeFromParent() - self.widget?.view.removeFromSuperview() - } - - func currentScreenChanged(to newScreen: DUXBetaBaseWidget) { - if let widget = self.widget { - widget.view.removeConstraints(widget.view.constraints) - } - self.configureConstraints() - } } extension SingleWidgetViewController: WidgetSelectionDelegate { - func widgetSelected(_ newWidget: DUXBetaBaseWidget?) { + func widgetSelected(_ newWidget: DUXBetaBaseWidget?, shouldShowCustomizationView:Bool) { + self.shouldShowCustomizationView = shouldShowCustomizationView self.widget = newWidget } } diff --git a/UXSDKBetaSample/UXSDKBetaSample/WidgetsListViewController.swift b/UXSDKBetaSample/UXSDKBetaSample/WidgetsListViewController.swift index bbbdeaa..1c91152 100644 --- a/UXSDKBetaSample/UXSDKBetaSample/WidgetsListViewController.swift +++ b/UXSDKBetaSample/UXSDKBetaSample/WidgetsListViewController.swift @@ -27,7 +27,7 @@ import UIKit import DJIUXSDKBeta protocol WidgetSelectionDelegate: class { - func widgetSelected(_ widget: DUXBetaBaseWidget?) + func widgetSelected(_ newWidget: DUXBetaBaseWidget?, shouldShowCustomizationView:Bool) } class WidgetsListViewController: UITableViewController { @@ -42,16 +42,46 @@ class WidgetsListViewController: UITableViewController { "Vision Widget" : "Widget to display the vision status/collision avodance status, of the aircraft. It's state depends on sensors availability, flight mode, and aircraft type.", ] - static let widgets:[DUXBetaBaseWidget] = [DUXBetaMapWidget(), - DUXBetaBatteryWidget(), - DUXBetaCompassWidget(), - DUXBetaDashboardWidget(), - DUXBetaVisionWidget()] - static let widgetTitles:[String] = ["Map Widget", - "Battery Widget", - "Compass Widget", - "Dashboard Widget", - "Vision Widget"] + static var widgetClosures: [() -> DUXBetaBaseWidget] { + let mapWidgetClosure: () -> DUXBetaBaseWidget = { + let mapWidget = DUXBetaMapWidget() + mapWidget.showFlyZoneLegend = false + return mapWidget + } + + let batteryWidgetClosure: () -> DUXBetaBaseWidget = { + return DUXBetaBatteryWidget() + } + + let compassWidgetClosure: () -> DUXBetaBaseWidget = { + return DUXBetaCompassWidget() + } + + let dashboardWidgetClosure: () -> DUXBetaBaseWidget = { + return DUXBetaDashboardWidget() + } + + let visionWidgetClosure: () -> DUXBetaBaseWidget = { + return DUXBetaVisionWidget() + } + + return [ + mapWidgetClosure, + batteryWidgetClosure, + compassWidgetClosure, + dashboardWidgetClosure, + visionWidgetClosure + ] + } + + static let widgetMetadata:[(String, Bool)] = [ + ("Map Widget", true), + ("Battery Widget", false), + ("Compass Widget", false), + ("Dashboard Widget", false), + ("Vision Widget", false) + ] + override func viewDidLoad() { super.viewDidLoad() @@ -63,10 +93,13 @@ class WidgetsListViewController: UITableViewController { // MARK: UITableViewDelegate public override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let widget = WidgetsListViewController.widgets[indexPath.row] - delegate?.widgetSelected(widget) + let widgetClosure = WidgetsListViewController.widgetClosures[indexPath.row] + let widget = widgetClosure() + let shouldShowCustomizationView = WidgetsListViewController.widgetMetadata[indexPath.row].1 + delegate?.widgetSelected(widget, shouldShowCustomizationView: shouldShowCustomizationView) if let singleWidgetViewController = delegate as? SingleWidgetViewController { - let title = WidgetsListViewController.widgetTitles[indexPath.row] + let title = WidgetsListViewController.widgetMetadata[indexPath.row].0 + singleWidgetViewController.shouldShowCustomizationView = shouldShowCustomizationView singleWidgetViewController.title = title singleWidgetViewController.widgetDescriptionLabel.text = WidgetsListViewController.widgetDescriptions[title] splitViewController?.showDetailViewController(singleWidgetViewController, sender: nil) @@ -76,12 +109,13 @@ class WidgetsListViewController: UITableViewController { // MARK: UITableViewDataSource public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return WidgetsListViewController.widgets.count + return WidgetsListViewController.widgetClosures.count } public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "WidgetsListCellIdentifier", for: indexPath) - cell.textLabel?.text = WidgetsListViewController.widgetTitles[indexPath.row] + let title = WidgetsListViewController.widgetMetadata[indexPath.row].0 + cell.textLabel?.text = title return cell }