mirror of
https://github.com/CopterExpress/clover.git
synced 2026-05-26 11:43:25 +00:00
Add mobile remote control for iOS
This commit is contained in:
17
apps/ios/.gitignore
vendored
Normal file
17
apps/ios/.gitignore
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# Xcode
|
||||
.DS_Store
|
||||
build/
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
!default.xcworkspace
|
||||
xcuserdata
|
||||
profile
|
||||
*.moved-aside
|
||||
DerivedData
|
||||
Pods/
|
||||
14
apps/ios/Podfile
Normal file
14
apps/ios/Podfile
Normal file
@@ -0,0 +1,14 @@
|
||||
project 'cleverrc.xcodeproj/'
|
||||
|
||||
# Uncomment the next line to define a global platform for your project
|
||||
# platform :ios, '9.0'
|
||||
|
||||
target 'cleverrc' do
|
||||
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
|
||||
use_frameworks!
|
||||
|
||||
# Pods for cleverrc
|
||||
pod 'SwiftSocket', '~> 2.0'
|
||||
pod 'NotificationBannerSwift'
|
||||
|
||||
end
|
||||
21
apps/ios/Podfile.lock
Normal file
21
apps/ios/Podfile.lock
Normal file
@@ -0,0 +1,21 @@
|
||||
PODS:
|
||||
- MarqueeLabel/Swift (3.1.4)
|
||||
- NotificationBannerSwift (1.5.4):
|
||||
- MarqueeLabel/Swift
|
||||
- SnapKit (~> 4.0)
|
||||
- SnapKit (4.0.0)
|
||||
- SwiftSocket (2.0.2)
|
||||
|
||||
DEPENDENCIES:
|
||||
- NotificationBannerSwift
|
||||
- SwiftSocket (~> 2.0)
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
MarqueeLabel: bf768455fe88d427f71476ebb23f9092b660f40b
|
||||
NotificationBannerSwift: 4f6666c8421dcf11be0812dd1093d932c15921af
|
||||
SnapKit: a42d492c16e80209130a3379f73596c3454b7694
|
||||
SwiftSocket: 6f4c9c63fbc5c1d61188936bb3c599fd546f40ae
|
||||
|
||||
PODFILE CHECKSUM: fd5199f69c3ee8c1fbc0dd582477d890c8b2a24f
|
||||
|
||||
COCOAPODS: 1.4.0
|
||||
444
apps/ios/cleverrc.xcodeproj/project.pbxproj
Normal file
444
apps/ios/cleverrc.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,444 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 48;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
7C0AB7AB202A744400BAED27 /* BinUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C0AB7AA202A744400BAED27 /* BinUtils.swift */; };
|
||||
7C51654120139237004D1F4D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C51654020139237004D1F4D /* AppDelegate.swift */; };
|
||||
7C51654320139237004D1F4D /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C51654220139237004D1F4D /* ViewController.swift */; };
|
||||
7C51654620139237004D1F4D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7C51654420139237004D1F4D /* Main.storyboard */; };
|
||||
7C51654820139237004D1F4D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7C51654720139237004D1F4D /* Assets.xcassets */; };
|
||||
7C51654B20139237004D1F4D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7C51654920139237004D1F4D /* LaunchScreen.storyboard */; };
|
||||
7C516553201526BA004D1F4D /* index.html in Resources */ = {isa = PBXBuildFile; fileRef = 7C516552201526BA004D1F4D /* index.html */; };
|
||||
7C51655520153180004D1F4D /* main.js in Resources */ = {isa = PBXBuildFile; fileRef = 7C51655420153180004D1F4D /* main.js */; };
|
||||
7CA401E22033CE17009FAA3B /* main.css in Resources */ = {isa = PBXBuildFile; fileRef = 7CA401E12033CE17009FAA3B /* main.css */; };
|
||||
7CA401E42033FA34009FAA3B /* telemetry.js in Resources */ = {isa = PBXBuildFile; fileRef = 7CA401E32033FA34009FAA3B /* telemetry.js */; };
|
||||
7CA401E6203471D9009FAA3B /* clever.svg in Resources */ = {isa = PBXBuildFile; fileRef = 7CA401E5203471D8009FAA3B /* clever.svg */; };
|
||||
C25141CAF1A7125F3CE29DDC /* Pods_cleverrc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C38C04523251039FF13DDCD /* Pods_cleverrc.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
5C38C04523251039FF13DDCD /* Pods_cleverrc.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_cleverrc.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
7C0AB7AA202A744400BAED27 /* BinUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BinUtils.swift; sourceTree = "<group>"; };
|
||||
7C45DCE9203A75A2009C73F5 /* roslib.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = roslib.js; sourceTree = "<group>"; };
|
||||
7C51653D20139237004D1F4D /* cleverrc.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = cleverrc.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
7C51654020139237004D1F4D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
7C51654220139237004D1F4D /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
7C51654520139237004D1F4D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
7C51654720139237004D1F4D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
7C51654A20139237004D1F4D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
7C51654C20139237004D1F4D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
7C516552201526BA004D1F4D /* index.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = index.html; sourceTree = "<group>"; };
|
||||
7C51655420153180004D1F4D /* main.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = main.js; sourceTree = "<group>"; };
|
||||
7CA401E12033CE17009FAA3B /* main.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = main.css; sourceTree = "<group>"; };
|
||||
7CA401E32033FA34009FAA3B /* telemetry.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = telemetry.js; sourceTree = "<group>"; };
|
||||
7CA401E5203471D8009FAA3B /* clever.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = clever.svg; sourceTree = "<group>"; };
|
||||
AAC9195BF3A9BF6942EF4D0B /* Pods-cleverrc.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-cleverrc.release.xcconfig"; path = "Pods/Target Support Files/Pods-cleverrc/Pods-cleverrc.release.xcconfig"; sourceTree = "<group>"; };
|
||||
CB200F4B933204EA97E0E2E4 /* Pods-cleverrc.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-cleverrc.debug.xcconfig"; path = "Pods/Target Support Files/Pods-cleverrc/Pods-cleverrc.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
7C51653A20139237004D1F4D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C25141CAF1A7125F3CE29DDC /* Pods_cleverrc.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
4FA3968F2242239E15A656D2 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CB200F4B933204EA97E0E2E4 /* Pods-cleverrc.debug.xcconfig */,
|
||||
AAC9195BF3A9BF6942EF4D0B /* Pods-cleverrc.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
66C638F0021EBE07741B26F3 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5C38C04523251039FF13DDCD /* Pods_cleverrc.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7C51653420139237004D1F4D = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
66C638F0021EBE07741B26F3 /* Frameworks */,
|
||||
4FA3968F2242239E15A656D2 /* Pods */,
|
||||
7C51653E20139237004D1F4D /* Products */,
|
||||
7C51653F20139237004D1F4D /* cleverrc */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7C51653E20139237004D1F4D /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7C51653D20139237004D1F4D /* cleverrc.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7C51653F20139237004D1F4D /* cleverrc */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7C45DCE9203A75A2009C73F5 /* roslib.js */,
|
||||
7C51654020139237004D1F4D /* AppDelegate.swift */,
|
||||
7C51654720139237004D1F4D /* Assets.xcassets */,
|
||||
7C0AB7AA202A744400BAED27 /* BinUtils.swift */,
|
||||
7C51654C20139237004D1F4D /* Info.plist */,
|
||||
7C51654920139237004D1F4D /* LaunchScreen.storyboard */,
|
||||
7C51654420139237004D1F4D /* Main.storyboard */,
|
||||
7C51654220139237004D1F4D /* ViewController.swift */,
|
||||
7CA401E5203471D8009FAA3B /* clever.svg */,
|
||||
7C516552201526BA004D1F4D /* index.html */,
|
||||
7CA401E12033CE17009FAA3B /* main.css */,
|
||||
7C51655420153180004D1F4D /* main.js */,
|
||||
7CA401E32033FA34009FAA3B /* telemetry.js */,
|
||||
);
|
||||
path = cleverrc;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
7C51653C20139237004D1F4D /* cleverrc */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 7C51654F20139237004D1F4D /* Build configuration list for PBXNativeTarget "cleverrc" */;
|
||||
buildPhases = (
|
||||
9F096121C4A02BCE9D4FD1B9 /* [CP] Check Pods Manifest.lock */,
|
||||
7C51653920139237004D1F4D /* Sources */,
|
||||
7C51653A20139237004D1F4D /* Frameworks */,
|
||||
7C51653B20139237004D1F4D /* Resources */,
|
||||
A37DBBAD5E44E632F8A8A204 /* [CP] Embed Pods Frameworks */,
|
||||
9BAB41D26FC0095C7C86B9DE /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = cleverrc;
|
||||
productName = cleverrc;
|
||||
productReference = 7C51653D20139237004D1F4D /* cleverrc.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
7C51653520139237004D1F4D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0920;
|
||||
LastUpgradeCheck = 0920;
|
||||
ORGANIZATIONNAME = "Copter Express";
|
||||
TargetAttributes = {
|
||||
7C51653C20139237004D1F4D = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 7C51653820139237004D1F4D /* Build configuration list for PBXProject "cleverrc" */;
|
||||
compatibilityVersion = "Xcode 8.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 7C51653420139237004D1F4D;
|
||||
productRefGroup = 7C51653E20139237004D1F4D /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
7C51653C20139237004D1F4D /* cleverrc */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
7C51653B20139237004D1F4D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7C51654B20139237004D1F4D /* LaunchScreen.storyboard in Resources */,
|
||||
7CA401E6203471D9009FAA3B /* clever.svg in Resources */,
|
||||
7CA401E42033FA34009FAA3B /* telemetry.js in Resources */,
|
||||
7C516553201526BA004D1F4D /* index.html in Resources */,
|
||||
7C51654820139237004D1F4D /* Assets.xcassets in Resources */,
|
||||
7CA401E22033CE17009FAA3B /* main.css in Resources */,
|
||||
7C51654620139237004D1F4D /* Main.storyboard in Resources */,
|
||||
7C51655520153180004D1F4D /* main.js in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
9BAB41D26FC0095C7C86B9DE /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-cleverrc/Pods-cleverrc-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
9F096121C4A02BCE9D4FD1B9 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-cleverrc-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
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;
|
||||
};
|
||||
A37DBBAD5E44E632F8A8A204 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${SRCROOT}/Pods/Target Support Files/Pods-cleverrc/Pods-cleverrc-frameworks.sh",
|
||||
"${BUILT_PRODUCTS_DIR}/MarqueeLabel/MarqueeLabel.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/NotificationBannerSwift/NotificationBannerSwift.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/SwiftSocket/SwiftSocket.framework",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MarqueeLabel.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/NotificationBannerSwift.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftSocket.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-cleverrc/Pods-cleverrc-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
7C51653920139237004D1F4D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7C51654320139237004D1F4D /* ViewController.swift in Sources */,
|
||||
7C51654120139237004D1F4D /* AppDelegate.swift in Sources */,
|
||||
7C0AB7AB202A744400BAED27 /* BinUtils.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
7C51654420139237004D1F4D /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
7C51654520139237004D1F4D /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
path = .;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7C51654920139237004D1F4D /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
7C51654A20139237004D1F4D /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
path = .;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
7C51654D20139237004D1F4D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = 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_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
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;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
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;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.2;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
7C51654E20139237004D1F4D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = 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_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
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;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
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;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.2;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
7C51655020139237004D1F4D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = CB200F4B933204EA97E0E2E4 /* Pods-cleverrc.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = 7QY6KJ2672;
|
||||
INFOPLIST_FILE = cleverrc/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = coex.cleverrc;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
7C51655120139237004D1F4D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = AAC9195BF3A9BF6942EF4D0B /* Pods-cleverrc.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = 7QY6KJ2672;
|
||||
INFOPLIST_FILE = cleverrc/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = coex.cleverrc;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
7C51653820139237004D1F4D /* Build configuration list for PBXProject "cleverrc" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
7C51654D20139237004D1F4D /* Debug */,
|
||||
7C51654E20139237004D1F4D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
7C51654F20139237004D1F4D /* Build configuration list for PBXNativeTarget "cleverrc" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
7C51655020139237004D1F4D /* Debug */,
|
||||
7C51655120139237004D1F4D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 7C51653520139237004D1F4D /* Project object */;
|
||||
}
|
||||
7
apps/ios/cleverrc.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
apps/ios/cleverrc.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:cleverrc.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
10
apps/ios/cleverrc.xcworkspace/contents.xcworkspacedata
generated
Normal file
10
apps/ios/cleverrc.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:cleverrc.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
46
apps/ios/cleverrc/AppDelegate.swift
Normal file
46
apps/ios/cleverrc/AppDelegate.swift
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// cleverrc
|
||||
//
|
||||
// Created by Oleg Kalachev on 20.01.2018.
|
||||
// Copyright © 2018 Copter Express. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
|
||||
func applicationWillResignActive(_ application: UIApplication) {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
func applicationDidEnterBackground(_ application: UIApplication) {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ application: UIApplication) {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "cleverios180.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "cleverios180-1.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "83.5x83.5",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"size" : "1024x1024",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
6
apps/ios/cleverrc/Assets.xcassets/Contents.json
Normal file
6
apps/ios/cleverrc/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
20
apps/ios/cleverrc/Assets.xcassets/Image.imageset/Contents.json
vendored
Normal file
20
apps/ios/cleverrc/Assets.xcassets/Image.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
29
apps/ios/cleverrc/Base.lproj/LaunchScreen.storyboard
Normal file
29
apps/ios/cleverrc/Base.lproj/LaunchScreen.storyboard
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.10586584359407425" green="0.10589186102151871" blue="0.10586420446634293" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
46
apps/ios/cleverrc/Base.lproj/Main.storyboard
Normal file
46
apps/ios/cleverrc/Base.lproj/Main.storyboard
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<device id="retina4_7" orientation="landscape">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="cleverrc" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<wkWebView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dtJ-LN-BYT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
|
||||
<color key="backgroundColor" red="0.12939286231994629" green="0.12942266464233398" blue="0.12939092516899109" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<wkWebViewConfiguration key="configuration">
|
||||
<audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/>
|
||||
<wkPreferences key="preferences"/>
|
||||
</wkWebViewConfiguration>
|
||||
</wkWebView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.1097869947552681" green="0.10981365293264389" blue="0.10978532582521439" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="dtJ-LN-BYT" firstAttribute="height" secondItem="8bC-Xf-vdC" secondAttribute="height" id="KRn-ag-67x"/>
|
||||
<constraint firstItem="dtJ-LN-BYT" firstAttribute="width" secondItem="8bC-Xf-vdC" secondAttribute="width" id="qOr-gg-e4M"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="webView" destination="dtJ-LN-BYT" id="bQ3-jy-o6E"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="138.0809595202399" y="124"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
453
apps/ios/cleverrc/BinUtils.swift
Normal file
453
apps/ios/cleverrc/BinUtils.swift
Normal file
@@ -0,0 +1,453 @@
|
||||
//
|
||||
// BinUtils.swift
|
||||
// BinUtils
|
||||
//
|
||||
// Created by Nicolas Seriot on 12/03/16.
|
||||
// Copyright © 2016 Nicolas Seriot. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreFoundation
|
||||
|
||||
// MARK: protocol UnpackedType
|
||||
|
||||
public protocol Unpackable {}
|
||||
|
||||
extension NSString: Unpackable {}
|
||||
extension Bool: Unpackable {}
|
||||
extension Int: Unpackable {}
|
||||
extension Double: Unpackable {}
|
||||
|
||||
// MARK: protocol DataConvertible
|
||||
|
||||
protocol DataConvertible {}
|
||||
|
||||
extension DataConvertible {
|
||||
|
||||
init?(data: Data) {
|
||||
guard data.count == MemoryLayout<Self>.size else { return nil }
|
||||
self = data.withUnsafeBytes { $0.pointee }
|
||||
}
|
||||
|
||||
init?(bytes: [UInt8]) {
|
||||
let data = Data(bytes:bytes)
|
||||
self.init(data:data)
|
||||
}
|
||||
|
||||
var data: Data {
|
||||
var value = self
|
||||
return Data(buffer: UnsafeBufferPointer(start: &value, count: 1))
|
||||
}
|
||||
}
|
||||
|
||||
extension Bool : DataConvertible { }
|
||||
|
||||
extension Int8 : DataConvertible { }
|
||||
extension Int16 : DataConvertible { }
|
||||
extension Int32 : DataConvertible { }
|
||||
extension Int64 : DataConvertible { }
|
||||
|
||||
extension UInt8 : DataConvertible { }
|
||||
extension UInt16 : DataConvertible { }
|
||||
extension UInt32 : DataConvertible { }
|
||||
extension UInt64 : DataConvertible { }
|
||||
|
||||
extension Float32 : DataConvertible { }
|
||||
extension Float64 : DataConvertible { }
|
||||
|
||||
// MARK: String extension
|
||||
|
||||
extension String {
|
||||
subscript (from:Int, to:Int) -> String {
|
||||
return NSString(string: self).substring(with: NSMakeRange(from, to-from))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Data extension
|
||||
|
||||
extension Data {
|
||||
var bytes : [UInt8] {
|
||||
return self.withUnsafeBytes {
|
||||
[UInt8](UnsafeBufferPointer(start: $0, count: self.count))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: functions
|
||||
|
||||
public func hexlify(_ data:Data) -> String {
|
||||
|
||||
// similar to hexlify() in Python's binascii module
|
||||
// https://docs.python.org/2/library/binascii.html
|
||||
|
||||
var s = String()
|
||||
var byte: UInt8 = 0
|
||||
|
||||
for i in 0 ..< data.count {
|
||||
NSData(data: data).getBytes(&byte, range: NSMakeRange(i, 1))
|
||||
s = s.appendingFormat("%02x", byte)
|
||||
}
|
||||
|
||||
return s as String
|
||||
}
|
||||
|
||||
public func unhexlify(_ string:String) -> Data? {
|
||||
|
||||
// similar to unhexlify() in Python's binascii module
|
||||
// https://docs.python.org/2/library/binascii.html
|
||||
|
||||
let s = string.uppercased().replacingOccurrences(of: " ", with: "")
|
||||
|
||||
let nonHexCharacterSet = CharacterSet(charactersIn: "0123456789ABCDEF").inverted
|
||||
if let range = s.rangeOfCharacter(from: nonHexCharacterSet) {
|
||||
print("-- found non hex character at range \(range)")
|
||||
return nil
|
||||
}
|
||||
|
||||
var data = Data(capacity: s.count / 2)
|
||||
|
||||
for i in stride(from: 0, to:s.count, by:2) {
|
||||
let byteString = s[i, i+2]
|
||||
let byte = UInt8(byteString.withCString { strtoul($0, nil, 16) })
|
||||
data.append([byte] as [UInt8], count: 1)
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
func readIntegerType<T:DataConvertible>(_ type:T.Type, bytes:[UInt8], loc:inout Int) -> T {
|
||||
let size = MemoryLayout<T>.size
|
||||
let sub = Array(bytes[loc..<(loc+size)])
|
||||
loc += size
|
||||
return T(bytes: sub)!
|
||||
}
|
||||
|
||||
func readFloatingPointType<T:DataConvertible>(_ type:T.Type, bytes:[UInt8], loc:inout Int, isBigEndian:Bool) -> T {
|
||||
let size = MemoryLayout<T>.size
|
||||
let sub = Array(bytes[loc..<(loc+size)])
|
||||
loc += size
|
||||
let sub_ = isBigEndian ? sub.reversed() : sub
|
||||
return T(bytes: sub_)!
|
||||
}
|
||||
|
||||
func isBigEndianFromMandatoryByteOrderFirstCharacter(_ format:String) -> Bool {
|
||||
|
||||
guard let firstChar = format.first else { assertionFailure("empty format"); return false }
|
||||
|
||||
let s = NSString(string: String(firstChar))
|
||||
let c = s.substring(to: 1)
|
||||
|
||||
if c == "@" { assertionFailure("native size and alignment is unsupported") }
|
||||
|
||||
if c == "=" || c == "<" { return false }
|
||||
if c == ">" || c == "!" { return true }
|
||||
|
||||
assertionFailure("format '\(format)' first character must be among '=<>!'")
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// akin to struct.calcsize(fmt)
|
||||
func numberOfBytesInFormat(_ format:String) -> Int {
|
||||
|
||||
var numberOfBytes = 0
|
||||
|
||||
var n = 0 // repeat counter
|
||||
|
||||
var mutableFormat = format
|
||||
|
||||
while !mutableFormat.isEmpty {
|
||||
|
||||
let c = mutableFormat.remove(at: mutableFormat.startIndex)
|
||||
|
||||
if let i = Int(String(c)) , 0...9 ~= i {
|
||||
if n > 0 { n *= 10 }
|
||||
n += i
|
||||
continue
|
||||
}
|
||||
|
||||
if c == "s" {
|
||||
numberOfBytes += max(n,1)
|
||||
n = 0
|
||||
continue
|
||||
}
|
||||
|
||||
for _ in 0..<max(n,1) {
|
||||
|
||||
switch(c) {
|
||||
|
||||
case "@", "<", "=", ">", "!", " ":
|
||||
()
|
||||
case "c", "b", "B", "x", "?":
|
||||
numberOfBytes += 1
|
||||
case "h", "H":
|
||||
numberOfBytes += 2
|
||||
case "i", "l", "I", "L", "f":
|
||||
numberOfBytes += 4
|
||||
case "q", "Q", "d":
|
||||
numberOfBytes += 8
|
||||
case "P":
|
||||
numberOfBytes += MemoryLayout<Int>.size
|
||||
default:
|
||||
assertionFailure("-- unsupported format \(c)")
|
||||
}
|
||||
}
|
||||
|
||||
n = 0
|
||||
}
|
||||
|
||||
return numberOfBytes
|
||||
}
|
||||
|
||||
func formatDoesMatchDataLength(_ format:String, data:Data) -> Bool {
|
||||
let sizeAccordingToFormat = numberOfBytesInFormat(format)
|
||||
let dataLength = data.count
|
||||
if sizeAccordingToFormat != dataLength {
|
||||
print("format \"\(format)\" expects \(sizeAccordingToFormat) bytes but data is \(dataLength) bytes")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/*
|
||||
pack() and unpack() should behave as Python's struct module https://docs.python.org/2/library/struct.html BUT:
|
||||
- native size and alignment '@' is not supported
|
||||
- as a consequence, the byte order specifier character is mandatory and must be among "=<>!"
|
||||
- native byte order '=' assumes a little-endian system (eg. Intel x86)
|
||||
- Pascal strings 'p' and native pointers 'P' are not supported
|
||||
*/
|
||||
|
||||
public enum BinUtilsError: Error {
|
||||
case formatDoesMatchDataLength(format:String, dataSize:Int)
|
||||
case unsupportedFormat(character:Character)
|
||||
}
|
||||
|
||||
public func pack(_ format:String, _ objects:[Any], _ stringEncoding:String.Encoding=String.Encoding.windowsCP1252) -> Data {
|
||||
|
||||
var objectsQueue = objects
|
||||
|
||||
var mutableFormat = format
|
||||
|
||||
var mutableData = Data()
|
||||
|
||||
var isBigEndian = false
|
||||
|
||||
let firstCharacter = mutableFormat.remove(at: mutableFormat.startIndex)
|
||||
|
||||
switch(firstCharacter) {
|
||||
case "<", "=":
|
||||
isBigEndian = false
|
||||
case ">", "!":
|
||||
isBigEndian = true
|
||||
case "@":
|
||||
assertionFailure("native size and alignment '@' is unsupported'")
|
||||
default:
|
||||
assertionFailure("unsupported format chacracter'")
|
||||
}
|
||||
|
||||
var n = 0 // repeat counter
|
||||
|
||||
while !mutableFormat.isEmpty {
|
||||
|
||||
let c = mutableFormat.remove(at: mutableFormat.startIndex)
|
||||
|
||||
if let i = Int(String(c)) , 0...9 ~= i {
|
||||
if n > 0 { n *= 10 }
|
||||
n += i
|
||||
continue
|
||||
}
|
||||
|
||||
var o : Any = 0
|
||||
|
||||
if c == "s" {
|
||||
o = objectsQueue.remove(at: 0)
|
||||
|
||||
guard let stringData = (o as! String).data(using: .utf8) else { assertionFailure(); return Data() }
|
||||
var bytes = stringData.bytes
|
||||
|
||||
let expectedSize = max(1, n)
|
||||
|
||||
// pad ...
|
||||
while bytes.count < expectedSize { bytes.append(0x00) }
|
||||
|
||||
// ... or trunk
|
||||
if bytes.count > expectedSize { bytes = Array(bytes[0..<expectedSize]) }
|
||||
|
||||
assert(bytes.count == expectedSize)
|
||||
|
||||
if isBigEndian { bytes = bytes.reversed() }
|
||||
|
||||
mutableData.append(bytes, count: bytes.count)
|
||||
|
||||
n = 0
|
||||
continue
|
||||
}
|
||||
|
||||
for _ in 0..<max(n,1) {
|
||||
|
||||
var bytes : [UInt8] = []
|
||||
|
||||
if c != "x" {
|
||||
o = objectsQueue.removeFirst()
|
||||
}
|
||||
|
||||
switch(c) {
|
||||
case "?":
|
||||
bytes = (o as! Bool) ? [0x01] : [0x00]
|
||||
case "c":
|
||||
let charAsString = (o as! NSString).substring(to: 1)
|
||||
guard let data = charAsString.data(using: stringEncoding) else {
|
||||
assertionFailure("cannot decode character \(charAsString) using encoding \(stringEncoding)")
|
||||
return Data()
|
||||
}
|
||||
bytes = data.bytes
|
||||
case "b":
|
||||
bytes = Int8(truncatingIfNeeded:o as! Int).data.bytes
|
||||
case "h":
|
||||
bytes = Int16(truncatingIfNeeded:o as! Int).data.bytes
|
||||
case "i", "l":
|
||||
bytes = Int32(truncatingIfNeeded:o as! Int).data.bytes
|
||||
case "q", "Q":
|
||||
bytes = Int64(o as! Int).data.bytes
|
||||
case "B":
|
||||
bytes = UInt8(truncatingIfNeeded:o as! Int).data.bytes
|
||||
case "H":
|
||||
bytes = UInt16(truncatingIfNeeded:o as! Int).data.bytes
|
||||
case "I", "L":
|
||||
bytes = UInt32(truncatingIfNeeded:o as! Int).data.bytes
|
||||
case "f":
|
||||
bytes = Float32(o as! Double).data.bytes
|
||||
case "d":
|
||||
bytes = Float64(o as! Double).data.bytes
|
||||
case "x":
|
||||
bytes = [0x00]
|
||||
default:
|
||||
assertionFailure("Unsupported packing format: \(c)")
|
||||
}
|
||||
|
||||
if isBigEndian { bytes = bytes.reversed() }
|
||||
let data = Data(bytes)
|
||||
mutableData.append(data)
|
||||
}
|
||||
|
||||
n = 0
|
||||
}
|
||||
|
||||
return mutableData
|
||||
}
|
||||
|
||||
public func unpack(_ format:String, _ data:Data, _ stringEncoding:String.Encoding=String.Encoding.windowsCP1252) throws -> [Unpackable] {
|
||||
|
||||
assert(CFByteOrderGetCurrent() == 1 /* CFByteOrderLittleEndian */, "\(#file) assumes little endian, but host is big endian")
|
||||
|
||||
let isBigEndian = isBigEndianFromMandatoryByteOrderFirstCharacter(format)
|
||||
|
||||
if formatDoesMatchDataLength(format, data: data) == false {
|
||||
throw BinUtilsError.formatDoesMatchDataLength(format:format, dataSize:data.count)
|
||||
}
|
||||
|
||||
var a : [Unpackable] = []
|
||||
|
||||
var loc = 0
|
||||
|
||||
let bytes = data.bytes
|
||||
|
||||
var n = 0 // repeat counter
|
||||
|
||||
var mutableFormat = format
|
||||
|
||||
mutableFormat.remove(at: mutableFormat.startIndex) // consume byte-order specifier
|
||||
|
||||
while !mutableFormat.isEmpty {
|
||||
|
||||
let c = mutableFormat.remove(at: mutableFormat.startIndex)
|
||||
|
||||
if let i = Int(String(c)) , 0...9 ~= i {
|
||||
if n > 0 { n *= 10 }
|
||||
n += i
|
||||
continue
|
||||
}
|
||||
|
||||
if c == "s" {
|
||||
let length = max(n,1)
|
||||
let sub = Array(bytes[loc..<loc+length])
|
||||
|
||||
guard let s = NSString(bytes: sub, length: length, encoding: stringEncoding.rawValue) else {
|
||||
assertionFailure("-- not a string: \(sub)")
|
||||
return []
|
||||
}
|
||||
|
||||
a.append(s)
|
||||
|
||||
loc += length
|
||||
|
||||
n = 0
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
for _ in 0..<max(n,1) {
|
||||
|
||||
var o : Unpackable?
|
||||
|
||||
switch(c) {
|
||||
|
||||
case "c":
|
||||
let optionalString = NSString(bytes: [bytes[loc]], length: 1, encoding: String.Encoding.utf8.rawValue)
|
||||
loc += 1
|
||||
guard let s = optionalString else { assertionFailure(); return [] }
|
||||
o = s
|
||||
case "b":
|
||||
let r = readIntegerType(Int8.self, bytes:bytes, loc:&loc)
|
||||
o = Int(r)
|
||||
case "B":
|
||||
let r = readIntegerType(UInt8.self, bytes:bytes, loc:&loc)
|
||||
o = Int(r)
|
||||
case "?":
|
||||
let r = readIntegerType(Bool.self, bytes:bytes, loc:&loc)
|
||||
o = r ? true : false
|
||||
case "h":
|
||||
let r = readIntegerType(Int16.self, bytes:bytes, loc:&loc)
|
||||
o = Int(isBigEndian ? Int16(bigEndian: r) : r)
|
||||
case "H":
|
||||
let r = readIntegerType(UInt16.self, bytes:bytes, loc:&loc)
|
||||
o = Int(isBigEndian ? UInt16(bigEndian: r) : r)
|
||||
case "i":
|
||||
fallthrough
|
||||
case "l":
|
||||
let r = readIntegerType(Int32.self, bytes:bytes, loc:&loc)
|
||||
o = Int(isBigEndian ? Int32(bigEndian: r) : r)
|
||||
case "I":
|
||||
fallthrough
|
||||
case "L":
|
||||
let r = readIntegerType(UInt32.self, bytes:bytes, loc:&loc)
|
||||
o = Int(isBigEndian ? UInt32(bigEndian: r) : r)
|
||||
case "q":
|
||||
let r = readIntegerType(Int64.self, bytes:bytes, loc:&loc)
|
||||
o = Int(isBigEndian ? Int64(bigEndian: r) : r)
|
||||
case "Q":
|
||||
let r = readIntegerType(UInt64.self, bytes:bytes, loc:&loc)
|
||||
o = Int(isBigEndian ? UInt64(bigEndian: r) : r)
|
||||
case "f":
|
||||
let r = readFloatingPointType(Float32.self, bytes:bytes, loc:&loc, isBigEndian:isBigEndian)
|
||||
o = Double(r)
|
||||
case "d":
|
||||
let r = readFloatingPointType(Float64.self, bytes:bytes, loc:&loc, isBigEndian:isBigEndian)
|
||||
o = Double(r)
|
||||
case "x":
|
||||
loc += 1
|
||||
case " ":
|
||||
()
|
||||
default:
|
||||
throw BinUtilsError.unsupportedFormat(character:c)
|
||||
}
|
||||
|
||||
if let o = o { a.append(o) }
|
||||
}
|
||||
|
||||
n = 0
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
46
apps/ios/cleverrc/Info.plist
Normal file
46
apps/ios/cleverrc/Info.plist
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Clever RC</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
70
apps/ios/cleverrc/ViewController.swift
Normal file
70
apps/ios/cleverrc/ViewController.swift
Normal file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// ViewController.swift
|
||||
// cleverrc
|
||||
//
|
||||
// Created by Oleg Kalachev on 20.01.2018.
|
||||
// Copyright © 2018 Copter Express. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import WebKit
|
||||
import SwiftSocket
|
||||
import NotificationBannerSwift
|
||||
|
||||
class ViewController: UIViewController, WKScriptMessageHandler {
|
||||
@IBOutlet weak var webView: WKWebView!
|
||||
let impactGenerator = UIImpactFeedbackGenerator(style: .medium)
|
||||
let notificationGenerator = UINotificationFeedbackGenerator()
|
||||
let udpSocket = UDPClient(address:"255.255.255.255", port: 35602)
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Don't lock screen
|
||||
UIApplication.shared.isIdleTimerDisabled = true
|
||||
|
||||
// Setup webview event handlers
|
||||
webView.configuration.userContentController.add(self, name: "control")
|
||||
webView.configuration.userContentController.add(self, name: "controlStart")
|
||||
webView.configuration.userContentController.add(self, name: "lowBattery")
|
||||
webView.configuration.userContentController.add(self, name: "notification")
|
||||
|
||||
// Load the main page
|
||||
let url = Bundle.main.url(forResource: "index", withExtension: "html")
|
||||
let requestObj = URLRequest(url: url!)
|
||||
webView.load(requestObj)
|
||||
|
||||
// Setup UDP broadcasting
|
||||
udpSocket.enableBroadcast()
|
||||
}
|
||||
|
||||
override func didReceiveMemoryWarning() {
|
||||
super.didReceiveMemoryWarning()
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
|
||||
if (message.name == "control") {
|
||||
// Send UDP control message
|
||||
let m = message.body as! NSDictionary;
|
||||
let d = pack("<hhhh", [m["x"]!, m["y"]!, m["z"]!, m["r"]!])
|
||||
_ = udpSocket.send(data: d)
|
||||
} else if (message.name == "lowBattery") {
|
||||
// Got low battery notification
|
||||
print("Low battery notification")
|
||||
notificationGenerator.notificationOccurred(.warning)
|
||||
} else if (message.name == "notification") {
|
||||
// Got notification message
|
||||
print(message)
|
||||
let m = message.body as! NSDictionary;
|
||||
let level = m["level"] as! Int
|
||||
if level == 4 {
|
||||
let banner = NotificationBanner(title: m["msg"] as! String, style: .warning)
|
||||
banner.show()
|
||||
} else {
|
||||
let banner = NotificationBanner(title: m["msg"] as! String, style: .danger)
|
||||
banner.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
84
apps/ios/cleverrc/clever.svg
Normal file
84
apps/ios/cleverrc/clever.svg
Normal file
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 52.5 52.5" enable-background="new 0 0 52.5 52.5" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="white" fill-opacity="0.5" d="M35.7,17.2c0.3-0.3,0.5-0.7,0.7-1.1c0.2-0.4,0.3-0.9,0.3-1.4c0-0.5-0.1-1-0.3-1.4c-0.2-0.5-0.5-0.9-0.8-1.3
|
||||
c-0.4-0.4-0.9-0.7-1.4-0.9c-0.6-0.2-1.2-0.3-1.8-0.2c-0.5,0.1-0.9,0.2-1.3,0.4c-0.2,0.1-0.4,0.3-0.6,0.4L30.2,12
|
||||
c-0.1,0.1-0.1,0.1-0.2,0.1c-0.1,0.1-0.3,0.2-0.4,0.2c-0.1,0.1-0.3,0.1-0.4,0.2c-0.1,0-0.2,0.1-0.4,0.1c-0.1,0-0.2,0-0.3,0
|
||||
c-0.6,0.1-1.3-0.1-1.9-0.4c-0.2-0.1-0.4-0.2-0.6-0.4c0,0-0.1-0.1-0.1-0.1c0,0-0.1-0.1-0.1-0.1c0,0,0,0-0.1-0.1
|
||||
c-0.1-0.1-0.1-0.2-0.1-0.3c0,0,0,0,0-0.1l0-6.5c-0.5-0.6-1.1-1.1-1.7-1.6c-0.9-0.7-1.9-1.4-3-1.8c-0.9-0.4-1.8-0.7-2.7-1
|
||||
c-0.9-0.2-1.7-0.3-2.6-0.4c-0.9-0.1-1.8,0-2.7,0.1c-0.7,0.1-1.5,0.2-2.2,0.5C9.4,0.9,8.1,1.5,7,2.2C6.2,2.7,5.4,3.3,4.7,3.9
|
||||
C4,4.6,3.4,5.3,2.8,6c-0.5,0.7-1,1.4-1.3,2.2C1.1,9,0.8,9.8,0.6,10.6c-0.2,0.7-0.4,1.4-0.4,2.1C0,13.7,0,14.6,0,15.6
|
||||
c0,0.8,0.2,1.7,0.4,2.5c0.2,0.9,0.5,1.7,0.8,2.5C1.8,21.8,2.5,23,3.4,24c0.3,0.4,0.7,0.8,1,1.1c0.2,0.2,0.3,0.3,0.5,0.5H11
|
||||
c0.1-0.1,0.1-0.2,0.1-0.2c0-0.1,0.1-0.1,0.1-0.2c0-0.1,0.1-0.1,0.1-0.2c0.1-0.4,0.2-0.8,0.1-1.1c0-0.1,0-0.1,0-0.2
|
||||
c0-0.1-0.1-0.1-0.1-0.2c0-0.1-0.1-0.2-0.2-0.2c0,0-0.1-0.1-0.1-0.1l0,0c0,0,0-0.1-0.1-0.1c0,0,0,0,0,0l-0.1-0.1
|
||||
c-0.1-0.1-0.2-0.3-0.3-0.4c-0.2-0.3-0.4-0.7-0.5-1c-0.1-0.3-0.2-0.7-0.3-1c-0.1-0.6-0.1-1.1,0-1.7c0.1-0.5,0.3-1,0.5-1.5
|
||||
c0.3-0.5,0.6-0.9,1-1.3c0.4-0.4,0.9-0.7,1.4-0.9c0.6-0.2,1.2-0.4,1.8-0.4c0.7,0,1.3,0.1,1.9,0.3c0.7,0.2,1.3,0.6,1.8,1.1
|
||||
c0.5,0.5,1,1.1,1.3,1.8c0.2,0.4,0.3,0.7,0.3,1.1c0.1,0.4,0.1,0.8,0.1,1.3c0,0.4-0.1,0.8-0.2,1.1c-0.1,0.3-0.3,0.7-0.4,1
|
||||
c-0.1,0.2-0.2,0.3-0.3,0.5c0,0.1-0.1,0.1-0.1,0.2l0,0l0,0l0,0.1c0,0,0,0.1-0.1,0.1l-0.1,0.1c0,0-0.1,0.1-0.1,0.1
|
||||
c-0.1,0.1-0.1,0.1-0.1,0.2c0,0.1-0.1,0.1-0.1,0.2c0,0.1,0,0.1,0,0.2c-0.1,0.3-0.1,0.7,0.1,1.1c0,0.1,0,0.1,0.1,0.2
|
||||
c0,0.1,0.1,0.1,0.1,0.2c0,0.1,0.1,0.2,0.2,0.3h7.2l0-7.5c0,0,0,0,0-0.1c0-0.1,0-0.1,0.1-0.2c0-0.1,0.1-0.1,0.1-0.2
|
||||
c0,0,0.1-0.1,0.1-0.1l0.1,0c0.1-0.1,0.2-0.1,0.3-0.2c0.5-0.3,1-0.5,1.6-0.6c0.2,0,0.3,0,0.5,0c0,0,0.1,0,0.1,0c0.1,0,0.1,0,0.2,0
|
||||
c0.1,0,0.2,0,0.4,0.1c0.3,0.1,0.7,0.2,0.9,0.4c0.1,0.1,0.2,0.1,0.3,0.2c0,0,0.1,0.1,0.1,0.1l0,0l-0.1,0.1c0,0,0,0,0,0l0.1-0.1
|
||||
l0.2,0.2c0.1,0.1,0.2,0.2,0.4,0.2c0.2,0.1,0.5,0.3,0.8,0.4c0.7,0.2,1.4,0.3,2,0.1c0.4-0.1,0.7-0.2,1.1-0.4
|
||||
C35.1,17.7,35.4,17.5,35.7,17.2z"/>
|
||||
<g>
|
||||
<polygon points="41.6,29.7 41.6,29.7 41.6,29.6 41.6,29.6 "/>
|
||||
<path fill="white" fill-opacity="0.5" d="M28.6,49.2c0.9,0.8,2,1.4,3,1.9c0.8,0.4,1.7,0.7,2.6,0.9c0.9,0.2,1.8,0.4,2.7,0.4c0.9,0.1,1.9,0,2.8-0.1
|
||||
c0.7-0.1,1.4-0.2,2.1-0.4c1.3-0.4,2.5-0.9,3.6-1.6c0.8-0.5,1.6-1.1,2.3-1.7c0.7-0.7,1.4-1.4,2-2.2c0.5-0.6,0.9-1.3,1.2-2
|
||||
c0.4-0.8,0.7-1.7,1-2.5c0.2-0.6,0.3-1.3,0.4-1.9c0.1-1,0.2-2,0.1-3c0-0.8-0.2-1.6-0.3-2.4c-0.2-0.9-0.5-1.7-0.8-2.6
|
||||
c-0.5-1.2-1.2-2.4-2.1-3.4c-0.3-0.4-0.6-0.8-1-1.1l-0.5-0.5h-6.1l-0.2,0.3c0,0.1-0.1,0.1-0.1,0.2c0,0.1-0.1,0.1-0.1,0.2
|
||||
c-0.1,0.4-0.2,0.8-0.1,1.1c0,0.1,0,0.1,0,0.2c0,0.1,0.1,0.1,0.1,0.2c0,0.1,0.1,0.2,0.2,0.3c0,0,0.1,0.1,0.1,0.1l0,0
|
||||
c0,0,0,0.1,0.1,0.1l0,0.1l0.1-0.1l0,0l0,0l0,0l0,0l0,0l0.1,0.1c0.2,0.2,0.3,0.4,0.5,0.7c0.3,0.5,0.5,1,0.6,1.5
|
||||
c0.1,0.7,0.1,1.5,0,2.2c-0.2,0.6-0.4,1.2-0.8,1.8c-0.3,0.4-0.7,0.8-1.1,1.1c-0.4,0.3-0.8,0.5-1.3,0.7c-0.5,0.2-1,0.3-1.5,0.3
|
||||
c-0.5,0-0.9,0-1.3-0.1c-0.5-0.1-1-0.3-1.4-0.6c-0.5-0.3-1-0.7-1.3-1.1c-0.4-0.5-0.7-1-0.9-1.6c-0.2-0.6-0.3-1.3-0.2-2
|
||||
c0-0.4,0.1-0.7,0.2-1c0.1-0.4,0.3-0.8,0.5-1.1c0.1-0.2,0.2-0.3,0.3-0.5c0-0.1,0.1-0.1,0.1-0.2l0.1,0c0,0,0,0,0,0l-0.1-0.1l0.1-0.1
|
||||
c0,0,0-0.1,0.1-0.1l0.1-0.1c0,0,0.1-0.1,0.1-0.1c0-0.1,0.1-0.1,0.1-0.2c0-0.1,0.1-0.1,0.1-0.2c0-0.1,0-0.1,0-0.2
|
||||
c0.1-0.3,0.1-0.7-0.1-1.1c0-0.1,0-0.1-0.1-0.2c0-0.1-0.1-0.2-0.1-0.2c0-0.1-0.1-0.2-0.1-0.2h-7.2l0,7.5c0,0,0,0,0,0.1
|
||||
c0,0.1-0.1,0.2-0.1,0.3c0,0,0,0.1-0.1,0.1c0,0-0.1,0.1-0.1,0.1c0,0,0,0-0.1,0c-0.1,0.1-0.3,0.2-0.4,0.3c-0.6,0.4-1.3,0.6-1.9,0.6
|
||||
c-0.1,0-0.2,0-0.3,0c-0.1,0-0.2,0-0.3,0c-0.4-0.1-0.7-0.2-1-0.4c-0.1-0.1-0.2-0.2-0.3-0.2c0,0-0.1-0.1-0.1-0.1h0l0,0l0,0
|
||||
c0,0-0.1-0.1-0.1-0.1L22,34.8c-0.2-0.2-0.4-0.3-0.6-0.4c-0.4-0.2-0.9-0.3-1.3-0.4c-0.3,0-0.7,0-1,0.1c-0.3,0.1-0.5,0.1-0.8,0.2
|
||||
c-0.5,0.2-1,0.5-1.3,0.9c-0.3,0.4-0.6,0.8-0.8,1.3C16,37,15.9,37.5,15.9,38c0,0.5,0.1,0.9,0.3,1.3c0.2,0.4,0.4,0.7,0.7,1
|
||||
c0.3,0.3,0.6,0.5,1,0.7c0.3,0.2,0.7,0.3,1,0.4c0.4,0.1,0.9,0.1,1.4,0c0.2,0,0.5-0.1,0.7-0.2c0.3-0.1,0.5-0.2,0.7-0.4
|
||||
c0.1-0.1,0.2-0.2,0.3-0.3l0.1-0.1l0,0l0,0c0,0,0,0,0,0l0.1-0.1c0.1,0,0.1-0.1,0.2-0.1c0.1-0.1,0.2-0.2,0.3-0.2
|
||||
c0.3-0.2,0.6-0.3,0.9-0.3c0.2,0,0.3,0,0.5,0h0.1c0.2,0,0.3,0,0.5,0c0.5,0.1,1,0.3,1.5,0.6c0.1,0.1,0.2,0.1,0.3,0.2l0.1,0
|
||||
c0,0,0.1,0.1,0.1,0.1c0,0.1,0.1,0.1,0.1,0.2c0,0.1,0,0.1,0.1,0.2c0,0,0,0,0,0.1l0,0v6.5C27.4,48.2,28,48.7,28.6,49.2z"/>
|
||||
<polygon points="22.3,34.9 22.3,34.9 22.3,34.9 22.3,34.9 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon points="40.7,30.2 40.7,30.2 40.7,30.2 "/>
|
||||
<path fill="white" fill-opacity="0.5" d="M49.2,24c0.7-0.9,1.3-1.8,1.8-2.9c0.4-0.7,0.7-1.5,0.9-2.3c0.2-0.8,0.4-1.7,0.5-2.6c0.2-1.7,0.1-3.4-0.3-5
|
||||
c-0.3-1.3-0.8-2.6-1.5-3.8c-0.4-0.7-0.9-1.4-1.4-2.1c-0.6-0.7-1.3-1.4-2-2c-0.6-0.5-1.3-1-2-1.4c-0.8-0.4-1.5-0.8-2.3-1.1
|
||||
c-1-0.4-2-0.6-3.1-0.7C39.3,0.1,38.9,0,38.5,0c-0.2,0-0.4,0-0.6,0h-0.1c-0.5,0-0.9,0-1.4,0.1c-0.8,0.1-1.7,0.2-2.5,0.4
|
||||
c-0.9,0.2-1.7,0.6-2.5,0.9c-0.8,0.4-1.5,0.8-2.2,1.3c-0.6,0.4-1.1,0.9-1.6,1.4c-0.2,0.2-0.5,0.5-0.7,0.7V11
|
||||
c0.1,0.1,0.2,0.1,0.2,0.1c0.1,0,0.1,0.1,0.2,0.1c0.1,0,0.1,0.1,0.2,0.1c0.4,0.1,0.8,0.2,1.1,0.1c0.1,0,0.1,0,0.2,0
|
||||
c0.1,0,0.1-0.1,0.2-0.1c0.1,0,0.2-0.1,0.3-0.2c0,0,0.1-0.1,0.1-0.1l0,0c0,0,0.1,0,0.1-0.1l0.1-0.1c0.2-0.1,0.3-0.2,0.5-0.3
|
||||
c0.3-0.2,0.7-0.4,1-0.5c0.3-0.1,0.6-0.2,1-0.2c0.6-0.1,1.1-0.1,1.7,0c0.5,0.1,1,0.3,1.5,0.5c0.5,0.3,0.9,0.6,1.3,1
|
||||
c0.4,0.4,0.7,0.9,0.9,1.4c0.2,0.6,0.4,1.2,0.4,1.8c0,0.6-0.1,1.3-0.3,1.9c-0.2,0.7-0.6,1.3-1,1.8c-0.5,0.5-1.1,1-1.8,1.3
|
||||
c-0.4,0.1-0.7,0.3-1.1,0.3c-0.4,0.1-0.8,0.1-1.3,0.1c-0.4,0-0.7-0.1-1.1-0.2c-0.4-0.1-0.7-0.3-1-0.5c-0.2-0.1-0.3-0.2-0.5-0.3
|
||||
c-0.1,0-0.1-0.1-0.2-0.1l-0.1-0.1c0,0-0.1,0-0.1-0.1c0,0-0.1-0.1-0.1-0.1c0,0-0.1-0.1-0.1-0.1c-0.1-0.1-0.1-0.1-0.2-0.1
|
||||
c-0.1,0-0.1-0.1-0.2-0.1c-0.1,0-0.1,0-0.2,0C28.4,18,28,18,27.6,18.1c-0.1,0-0.1,0-0.2,0.1c-0.1,0-0.2,0.1-0.2,0.1
|
||||
c-0.1,0-0.2,0.1-0.2,0.1v7.2l7.5,0c0,0,0,0,0.1,0c0.1,0,0.2,0.1,0.3,0.1c0,0,0.1,0,0.1,0.1c0,0,0.1,0.1,0.1,0.1l0.1,0.1
|
||||
c0.1,0.1,0.2,0.3,0.3,0.4c0.4,0.6,0.6,1.3,0.6,1.9c0,0.1,0,0.2,0,0.3c0,0.1,0,0.2,0,0.3c-0.1,0.4-0.2,0.7-0.4,1
|
||||
c-0.1,0.1-0.2,0.2-0.2,0.3c0,0-0.1,0.1-0.1,0.1l0,0l0,0l-0.2,0.2c-0.1,0.1-0.2,0.2-0.2,0.3c-0.1,0.2-0.3,0.5-0.3,0.7
|
||||
c-0.2,0.7-0.3,1.4-0.1,2c0.1,0.4,0.2,0.7,0.4,1.1c0.2,0.4,0.5,0.7,0.8,0.9c0.3,0.3,0.7,0.5,1.1,0.7c0.4,0.2,0.9,0.3,1.4,0.3
|
||||
c0,0,0,0,0,0c0.5,0,1-0.1,1.4-0.3c0.5-0.2,0.9-0.5,1.3-0.8c0.4-0.4,0.7-0.9,0.9-1.4c0.2-0.6,0.3-1.2,0.2-1.8
|
||||
c-0.1-0.5-0.2-0.9-0.5-1.3c-0.1-0.2-0.3-0.4-0.4-0.6l-0.1-0.1l0,0l0,0l0,0l0,0l0-0.1l0,0l-0.1,0.1l-0.1-0.1
|
||||
c-0.1-0.1-0.1-0.1-0.1-0.2c-0.1-0.1-0.2-0.3-0.2-0.4c-0.1-0.1-0.1-0.3-0.2-0.4c0-0.1-0.1-0.2-0.1-0.4c0-0.1,0-0.2,0-0.3
|
||||
c-0.1-0.6,0.1-1.3,0.4-1.9c0.1-0.2,0.2-0.4,0.4-0.6c0,0,0.1-0.1,0.1-0.1c0,0,0.1-0.1,0.1-0.1c0,0,0.1,0,0.1-0.1
|
||||
c0.1-0.1,0.2-0.1,0.3-0.1c0,0,0,0,0.1,0l0,0h6.5C48.2,25.1,48.7,24.5,49.2,24z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="XMLID_14_">
|
||||
</g>
|
||||
<g id="XMLID_15_">
|
||||
</g>
|
||||
<g id="XMLID_16_">
|
||||
</g>
|
||||
<g id="XMLID_17_">
|
||||
</g>
|
||||
<g id="XMLID_18_">
|
||||
</g>
|
||||
<g id="XMLID_19_">
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.4 KiB |
23
apps/ios/cleverrc/index.html
Normal file
23
apps/ios/cleverrc/index.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, minimal-ui">
|
||||
<link rel="stylesheet" href="main.css">
|
||||
<script src="roslib.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="telemetry"><span class="mode">DISCONNECTED</span></div>
|
||||
<div class="battery"></div>
|
||||
<div class="logo"></div>
|
||||
<div class="container">
|
||||
<div class="stick stick-left">
|
||||
<div class="stick-pointer"></div>
|
||||
</div>
|
||||
<div class="stick stick-right">
|
||||
<div class="stick-pointer"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="main.js" type="text/javascript"></script>
|
||||
<script src="telemetry.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
91
apps/ios/cleverrc/main.css
Normal file
91
apps/ios/cleverrc/main.css
Normal file
@@ -0,0 +1,91 @@
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
user-select: none;
|
||||
font-family: sans-serif;
|
||||
background: #212121;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.stick {
|
||||
border-radius: 50%;
|
||||
width: 5cm;
|
||||
height: 5cm;
|
||||
position: relative;
|
||||
transform: translateZ(0);
|
||||
border: 4px solid rgba(255,255,255,.4);
|
||||
box-shadow: 0 0 0 1px rgba(0,0,0,.2), inset 0 0 0 1px rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
.stick-pointer {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(255,255,255,.25);
|
||||
box-shadow: 0 0 10px rgba(0,0,0,.3);
|
||||
width: 3cm;
|
||||
height: 3cm;
|
||||
margin-left: -1.5cm;
|
||||
margin-top: -1.5cm;
|
||||
top: 2.5cm;
|
||||
left: 2.5cm;
|
||||
pointer-events: none;
|
||||
transform: translateZ(0);
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.telemetry {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
top: 30px;
|
||||
font-size: 20px;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
body.armed .telemetry .mode {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@keyframes scale {
|
||||
0% { transform: scale(1.0); }
|
||||
50% { transform: scale(1.2); }
|
||||
100% { transform: scale(1.0); }
|
||||
}
|
||||
|
||||
.battery {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
bottom: 30px;
|
||||
font-size: 20px;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
body.low-battery .battery {
|
||||
color: #ff554b;
|
||||
animation: scale 0.3s 1 ease-in-out}
|
||||
|
||||
.logo {
|
||||
position: absolute;
|
||||
background: url(clever.svg);
|
||||
-webkit-background-size: 50px;
|
||||
background-size: 50px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-top: -25px;
|
||||
margin-left: -25px;
|
||||
font-size: 20px;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
126
apps/ios/cleverrc/main.js
Normal file
126
apps/ios/cleverrc/main.js
Normal file
@@ -0,0 +1,126 @@
|
||||
function throttle(func, ms) {
|
||||
var isThrottled = false,
|
||||
savedArgs,
|
||||
savedThis;
|
||||
|
||||
function wrapper() {
|
||||
if (isThrottled) {
|
||||
savedArgs = arguments;
|
||||
savedThis = this;
|
||||
return;
|
||||
}
|
||||
func.apply(this, arguments);
|
||||
isThrottled = true;
|
||||
setTimeout(function() {
|
||||
isThrottled = false;
|
||||
if (savedArgs) {
|
||||
wrapper.apply(savedThis, savedArgs);
|
||||
savedArgs = savedThis = null;
|
||||
}
|
||||
}, ms);
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
function callNativeApp(name, msg) {
|
||||
try {
|
||||
webkit.messageHandlers[name].postMessage(msg);
|
||||
return true;
|
||||
} catch(err) {
|
||||
console.warn('The native context does not exist yet');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var rcLastPublish = null;
|
||||
|
||||
function rcPublish() {
|
||||
callNativeApp('control', controlMessage);
|
||||
rcLastPublish = new Date();
|
||||
}
|
||||
|
||||
rcPublishThrottled = throttle(rcPublish, 30);
|
||||
|
||||
setInterval(function() {
|
||||
if (rcLastPublish !== null && new Date() - rcLastPublish > 800) {
|
||||
rcPublishThrottled();
|
||||
}
|
||||
}, 50);
|
||||
|
||||
var body = document.querySelector('body');
|
||||
var stickLeft = document.querySelector('.stick-left');
|
||||
var stickRight = document.querySelector('.stick-right');
|
||||
|
||||
var controlMessage = { x: 0, y: 0, z: 0, r: 0 };
|
||||
|
||||
function onStickTouchMove(touch) {
|
||||
var target = touch.target;
|
||||
var targetRect = target.getBoundingClientRect();
|
||||
var stickPointer = target.querySelector('.stick-pointer');
|
||||
|
||||
var offsetX = touch.clientX - targetRect.left;
|
||||
var offsetY = touch.clientY - targetRect.top;
|
||||
|
||||
var x = 2 * offsetX / targetRect.width;
|
||||
var y = 2 * offsetY / targetRect.height;
|
||||
|
||||
x = Math.max(0, x);
|
||||
x = Math.min(2, x);
|
||||
y = Math.max(0, y);
|
||||
y = Math.min(2, y);
|
||||
|
||||
stickPointer.style.left = (x * 50) + '%';
|
||||
stickPointer.style.top = (y * 50) + '%';
|
||||
|
||||
x -= 1;
|
||||
y = 1 - y;
|
||||
|
||||
if (target.matches('.stick-left')) {
|
||||
controlMessage.z = Math.round((y + 1) * 500);
|
||||
controlMessage.r = Math.round(x * 1000);
|
||||
} else if (target.matches('.stick-right')) {
|
||||
controlMessage.x = Math.round(y * 1000);
|
||||
controlMessage.y = Math.round(x * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
body.addEventListener('touchmove', function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
function stickTouchStart(e) {
|
||||
setControlMode();
|
||||
callNativeApp('controlStart');
|
||||
onStickTouchMove(e.changedTouches[0]);
|
||||
rcPublishThrottled();
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
function stickTouchMove(e) {
|
||||
onStickTouchMove(e.changedTouches[0]);
|
||||
rcPublishThrottled();
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
function stickTouchEnd(e) {
|
||||
var pointer = e.target.querySelector('.stick-pointer');
|
||||
if (e.target.matches('.stick-left')) {
|
||||
controlMessage.r = 0;
|
||||
pointer.style.left = '50%';
|
||||
} else if (e.target.matches('.stick-right')) {
|
||||
controlMessage.x = 0;
|
||||
controlMessage.y = 0;
|
||||
pointer.style.left = '50%';
|
||||
pointer.style.top = '50%';
|
||||
}
|
||||
rcPublishThrottled();
|
||||
}
|
||||
|
||||
stickLeft.addEventListener('touchmove', stickTouchMove);
|
||||
stickRight.addEventListener('touchmove', stickTouchMove);
|
||||
stickLeft.addEventListener('touchstart', stickTouchStart);
|
||||
stickRight.addEventListener('touchstart', stickTouchStart);
|
||||
stickLeft.addEventListener('touchend', stickTouchEnd);
|
||||
stickRight.addEventListener('touchend', stickTouchEnd);
|
||||
3693
apps/ios/cleverrc/roslib.js
Normal file
3693
apps/ios/cleverrc/roslib.js
Normal file
File diff suppressed because it is too large
Load Diff
85
apps/ios/cleverrc/telemetry.js
Normal file
85
apps/ios/cleverrc/telemetry.js
Normal file
@@ -0,0 +1,85 @@
|
||||
var url = 'ws://192.168.11.1:9090';
|
||||
var modeEl = document.querySelector('.telemetry .mode');
|
||||
var batteryEl = document.querySelector('.battery');
|
||||
|
||||
var ros = new ROSLIB.Ros({ url: url });
|
||||
|
||||
ros.on('connection', function () {
|
||||
body.classList.add('connected');
|
||||
});
|
||||
|
||||
ros.on('close', function () {
|
||||
body.classList.remove('connected');
|
||||
modeEl.classList.remove('armed');
|
||||
modeEl.innerHTML = 'DISCONNECTED';
|
||||
batteryEl.innerHTML = '';
|
||||
setTimeout(function() {
|
||||
modeEl.innerHTML = 'RECONNECTING';
|
||||
ros.connect(url);
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
var fcuState;
|
||||
|
||||
new ROSLIB.Topic({
|
||||
ros: ros,
|
||||
name: '/state_latched',
|
||||
messageType: 'mavros_msgs/State'
|
||||
}).subscribe(function(message) {
|
||||
body.classList.toggle('fcu-disconnected', !message.connected);
|
||||
body.classList.toggle('armed', message.armed);
|
||||
fcuState = message;
|
||||
modeEl.classList.toggle('armed', fcuState.armed);
|
||||
modeEl.innerHTML = message.connected ? fcuState.mode : 'DISCONNECTED FROM FCU';
|
||||
console.log('state', message);
|
||||
});
|
||||
|
||||
function notifyLowBattery() {
|
||||
callNativeApp('lowBattery');
|
||||
}
|
||||
|
||||
notifyLowBatteryThrottled = throttle(notifyLowBattery, 10000);
|
||||
|
||||
new ROSLIB.Topic({
|
||||
ros: ros,
|
||||
name: '/mavros/battery',
|
||||
messageType: 'sensor_msgs/BatteryState',
|
||||
throttle_rate: 5000
|
||||
}).subscribe(function(message) {
|
||||
var LOW_BATTERY = 3.8;
|
||||
batteryEl.innerHTML = (message.cell_voltage[0].toFixed(2) + ' V') || '';
|
||||
|
||||
if (message.cell_voltage[0] < LOW_BATTERY) {
|
||||
console.log('low battery');
|
||||
callNativeApp('lowBattery');
|
||||
body.classList.remove('low-battery');
|
||||
void body.offsetWidth; // trick for repeating animation
|
||||
body.classList.add('low-battery');
|
||||
} else {
|
||||
body.classList.remove('low-battery');
|
||||
}
|
||||
});
|
||||
|
||||
new ROSLIB.Topic({
|
||||
ros: ros,
|
||||
name: '/rosout_agg',
|
||||
messageType: 'rosgraph_msgs/Log'
|
||||
}).subscribe(function(message) {
|
||||
if(message.level >= 4) {
|
||||
if (message.msg.startsWith('CMD: ')) {
|
||||
return;
|
||||
}
|
||||
callNativeApp('notification', message);
|
||||
}
|
||||
});
|
||||
|
||||
var setMode = new ROSLIB.Service({
|
||||
ros: ros,
|
||||
name : '/mavros/set_mode',
|
||||
serviceType : 'mavros_msgs/SetMode'
|
||||
});
|
||||
|
||||
function setControlMode() {
|
||||
var CONTROL_MODE = 'STABILIZED';
|
||||
setMode.callService(new ROSLIB.ServiceRequest({ custom_mode: CONTROL_MODE }));
|
||||
}
|
||||
Reference in New Issue
Block a user