diff --git a/EspressifProvision/EspressifProvision.xcodeproj/project.pbxproj b/EspressifProvision/EspressifProvision.xcodeproj/project.pbxproj index 07fd394..4451932 100644 --- a/EspressifProvision/EspressifProvision.xcodeproj/project.pbxproj +++ b/EspressifProvision/EspressifProvision.xcodeproj/project.pbxproj @@ -44,9 +44,20 @@ 14DE671C20EC94C600941522 /* ConfigureAVS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14DE671B20EC94C600941522 /* ConfigureAVS.swift */; }; 14DE671E20ECD04100941522 /* BLETransport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14DE671D20ECD04100941522 /* BLETransport.swift */; }; 7E89B3398606A35D1BCB7893 /* Pods_EspressifProvisionAll_EspressifProvision.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9FC5952F5F6F4A07A0ED190E /* Pods_EspressifProvisionAll_EspressifProvision.framework */; }; + F1342A48229D697B00AD8626 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1342A47229D697B00AD8626 /* Constants.swift */; }; + F1342A4B229E7D8700AD8626 /* DeviceListTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1342A4A229E7D8700AD8626 /* DeviceListTableViewCell.swift */; }; F184C9E4228C3E8B0034C5B7 /* AESDecryptor.m in Sources */ = {isa = PBXBuildFile; fileRef = F184C9E3228C3E8B0034C5B7 /* AESDecryptor.m */; }; + F18C3AB6229BECE1007C197F /* AlexaDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = F18C3AB5229BECE1007C197F /* AlexaDevice.swift */; }; + F18C3AB8229BEDB2007C197F /* ScannedLocalDevicesVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = F18C3AB7229BEDB2007C197F /* ScannedLocalDevicesVC.swift */; }; + F18C3ABE229BF4D4007C197F /* SSDPService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F18C3ABC229BF4D4007C197F /* SSDPService.swift */; }; + F18C3ABF229BF4D4007C197F /* SSDPDiscovery.swift in Sources */ = {isa = PBXBuildFile; fileRef = F18C3ABD229BF4D4007C197F /* SSDPDiscovery.swift */; }; F1DCEC292296CB94005918FE /* ScanWifiList.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1DCEC282296CB94005918FE /* ScanWifiList.swift */; }; F1DCEC2D2297D577005918FE /* WifiListTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1DCEC2C2297D577005918FE /* WifiListTableViewCell.swift */; }; + F1DD7095229FC8620092DAB9 /* AmazonEmberDisplay_Lt.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F1DD7094229FC8590092DAB9 /* AmazonEmberDisplay_Lt.ttf */; }; + F1DD7097229FCAB10092DAB9 /* Bookerly-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F1DD7096229FCAB10092DAB9 /* Bookerly-Italic.ttf */; }; + F1DD7099229FCEDE0092DAB9 /* DeviceDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1DD7098229FCEDE0092DAB9 /* DeviceDetailViewController.swift */; }; + F1DD709B229FDE6C0092DAB9 /* AmazonEmberDisplay_Md.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F1DD709A229FDE6C0092DAB9 /* AmazonEmberDisplay_Md.ttf */; }; + F1DD709D229FDF5E0092DAB9 /* AmazonEmberDisplay_Rg.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F1DD709C229FDF5E0092DAB9 /* AmazonEmberDisplay_Rg.ttf */; }; F1F339572296703C000F53A0 /* wifi_scan.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1F339562296703C000F53A0 /* wifi_scan.pb.swift */; }; F6D7C9B0F5FDCEEFFA78A8C8 /* Pods_EspressifProvisionAll_EspressifProvisionTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9BEBDCCD5B5E7E9D6B8F9AE3 /* Pods_EspressifProvisionAll_EspressifProvisionTests.framework */; }; /* End PBXBuildFile section */ @@ -140,10 +151,21 @@ D2B4EC5704D46C3EA9A47720 /* Pods-EspressifProvisionAll-EspressifProvisionTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-EspressifProvisionAll-EspressifProvisionTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-EspressifProvisionAll-EspressifProvisionTests/Pods-EspressifProvisionAll-EspressifProvisionTests.release.xcconfig"; sourceTree = ""; }; D3C0A52210E731723240B81F /* Pods-EspressifProvisionAll-EspressifProvision.blesec1avs-release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-EspressifProvisionAll-EspressifProvision.blesec1avs-release.xcconfig"; path = "Pods/Target Support Files/Pods-EspressifProvisionAll-EspressifProvision/Pods-EspressifProvisionAll-EspressifProvision.blesec1avs-release.xcconfig"; sourceTree = ""; }; EA24507D63588F8C9C0C451B /* Pods-EspressifProvisionAll-EspressifProvision.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-EspressifProvisionAll-EspressifProvision.debug.xcconfig"; path = "Pods/Target Support Files/Pods-EspressifProvisionAll-EspressifProvision/Pods-EspressifProvisionAll-EspressifProvision.debug.xcconfig"; sourceTree = ""; }; + F1342A47229D697B00AD8626 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; + F1342A4A229E7D8700AD8626 /* DeviceListTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceListTableViewCell.swift; sourceTree = ""; }; F184C9E2228C3E8B0034C5B7 /* AESDecryptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AESDecryptor.h; sourceTree = ""; }; F184C9E3228C3E8B0034C5B7 /* AESDecryptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AESDecryptor.m; sourceTree = ""; }; + F18C3AB5229BECE1007C197F /* AlexaDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlexaDevice.swift; sourceTree = ""; }; + F18C3AB7229BEDB2007C197F /* ScannedLocalDevicesVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScannedLocalDevicesVC.swift; sourceTree = ""; }; + F18C3ABC229BF4D4007C197F /* SSDPService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SSDPService.swift; sourceTree = ""; }; + F18C3ABD229BF4D4007C197F /* SSDPDiscovery.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SSDPDiscovery.swift; sourceTree = ""; }; F1DCEC282296CB94005918FE /* ScanWifiList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanWifiList.swift; sourceTree = ""; }; F1DCEC2C2297D577005918FE /* WifiListTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiListTableViewCell.swift; sourceTree = ""; }; + F1DD7094229FC8590092DAB9 /* AmazonEmberDisplay_Lt.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = AmazonEmberDisplay_Lt.ttf; sourceTree = ""; }; + F1DD7096229FCAB10092DAB9 /* Bookerly-Italic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Bookerly-Italic.ttf"; sourceTree = ""; }; + F1DD7098229FCEDE0092DAB9 /* DeviceDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceDetailViewController.swift; sourceTree = ""; }; + F1DD709A229FDE6C0092DAB9 /* AmazonEmberDisplay_Md.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = AmazonEmberDisplay_Md.ttf; sourceTree = ""; }; + F1DD709C229FDF5E0092DAB9 /* AmazonEmberDisplay_Rg.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = AmazonEmberDisplay_Rg.ttf; sourceTree = ""; }; F1F339562296703C000F53A0 /* wifi_scan.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = wifi_scan.pb.swift; sourceTree = ""; }; F5A6E92635049FCEB2D5787E /* Pods-EspressifProvisionAll-EspressifProvision.wifisec1avs-debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-EspressifProvisionAll-EspressifProvision.wifisec1avs-debug.xcconfig"; path = "Pods/Target Support Files/Pods-EspressifProvisionAll-EspressifProvision/Pods-EspressifProvisionAll-EspressifProvision.wifisec1avs-debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -203,6 +225,9 @@ 1431462520DE994B0017E119 /* EspressifProvision */ = { isa = PBXGroup; children = ( + F1DD7093229FC83A0092DAB9 /* fonts */, + F1342A46229D696700AD8626 /* Utilities */, + F18C3AB4229BEC8E007C197F /* Model */, 143146B020EA303C0017E119 /* EspressifProvision.entitlements */, 1431468F20E387C60017E119 /* proto */, 143146B120EB221E0017E119 /* ui */, @@ -305,6 +330,7 @@ 143146B120EB221E0017E119 /* ui */ = { isa = PBXGroup; children = ( + F1342A49229E7D5A00AD8626 /* ManageDevice */, 143146A920EA29E90017E119 /* LoginWithAmazonViewController.swift */, 143146B220EB22470017E119 /* ProvisionLandingViewController.swift */, 143146B420EB273B0017E119 /* ProvisionViewController.swift */, @@ -380,6 +406,43 @@ name = Frameworks; sourceTree = ""; }; + F1342A46229D696700AD8626 /* Utilities */ = { + isa = PBXGroup; + children = ( + F18C3ABB229BF4D4007C197F /* SSDPClient */, + F1342A47229D697B00AD8626 /* Constants.swift */, + ); + path = Utilities; + sourceTree = ""; + }; + F1342A49229E7D5A00AD8626 /* ManageDevice */ = { + isa = PBXGroup; + children = ( + F18C3AB7229BEDB2007C197F /* ScannedLocalDevicesVC.swift */, + F1342A4A229E7D8700AD8626 /* DeviceListTableViewCell.swift */, + F1DD7098229FCEDE0092DAB9 /* DeviceDetailViewController.swift */, + ); + path = ManageDevice; + sourceTree = ""; + }; + F18C3AB4229BEC8E007C197F /* Model */ = { + isa = PBXGroup; + children = ( + F18C3AB5229BECE1007C197F /* AlexaDevice.swift */, + ); + path = Model; + sourceTree = ""; + }; + F18C3ABB229BF4D4007C197F /* SSDPClient */ = { + isa = PBXGroup; + children = ( + F18C3ABC229BF4D4007C197F /* SSDPService.swift */, + F18C3ABD229BF4D4007C197F /* SSDPDiscovery.swift */, + ); + name = SSDPClient; + path = ../SSDPClient; + sourceTree = ""; + }; F1DCEC272296CB7D005918FE /* wifi */ = { isa = PBXGroup; children = ( @@ -389,6 +452,17 @@ path = wifi; sourceTree = ""; }; + F1DD7093229FC83A0092DAB9 /* fonts */ = { + isa = PBXGroup; + children = ( + F1DD7094229FC8590092DAB9 /* AmazonEmberDisplay_Lt.ttf */, + F1DD709A229FDE6C0092DAB9 /* AmazonEmberDisplay_Md.ttf */, + F1DD709C229FDF5E0092DAB9 /* AmazonEmberDisplay_Rg.ttf */, + F1DD7096229FCAB10092DAB9 /* Bookerly-Italic.ttf */, + ); + path = fonts; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -513,6 +587,10 @@ 1431463120DE994C0017E119 /* LaunchScreen.storyboard in Resources */, 1431462E20DE994C0017E119 /* Assets.xcassets in Resources */, 1431462C20DE994B0017E119 /* Main.storyboard in Resources */, + F1DD7097229FCAB10092DAB9 /* Bookerly-Italic.ttf in Resources */, + F1DD709D229FDF5E0092DAB9 /* AmazonEmberDisplay_Rg.ttf in Resources */, + F1DD709B229FDE6C0092DAB9 /* AmazonEmberDisplay_Md.ttf in Resources */, + F1DD7095229FC8620092DAB9 /* AmazonEmberDisplay_Lt.ttf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -586,12 +664,14 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-EspressifProvisionAll-EspressifProvision/Pods-EspressifProvisionAll-EspressifProvision-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/BlueSocket/Socket.framework", "${BUILT_PRODUCTS_DIR}/Curve25519/Curve25519.framework", "${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework", "${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Socket.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Curve25519.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MBProgressHUD.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework", @@ -608,12 +688,14 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-EspressifProvisionAll-EspressifProvisionTests/Pods-EspressifProvisionAll-EspressifProvisionTests-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/BlueSocket/Socket.framework", "${BUILT_PRODUCTS_DIR}/Curve25519/Curve25519.framework", "${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework", "${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Socket.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Curve25519.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MBProgressHUD.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework", @@ -649,7 +731,11 @@ buildActionMask = 2147483647; files = ( 1431468220DEB6F50017E119 /* Security0.swift in Sources */, + F1342A48229D697B00AD8626 /* Constants.swift in Sources */, + F1DD7099229FCEDE0092DAB9 /* DeviceDetailViewController.swift in Sources */, 1431469820E387C60017E119 /* sec1.pb.swift in Sources */, + F18C3AB6229BECE1007C197F /* AlexaDevice.swift in Sources */, + F18C3ABE229BF4D4007C197F /* SSDPService.swift in Sources */, 14DE671E20ECD04100941522 /* BLETransport.swift in Sources */, 149774DF210C87AB00022841 /* DataExtensions.swift in Sources */, 1431468E20E3823F0017E119 /* Provision.swift in Sources */, @@ -662,10 +748,13 @@ 149774DD210C799900022841 /* CryptoAES.swift in Sources */, 1431466920DEAD1A0017E119 /* SoftAPTransport.swift in Sources */, 1431469B20E387C60017E119 /* constants.pb.swift in Sources */, + F1342A4B229E7D8700AD8626 /* DeviceListTableViewCell.swift in Sources */, 149774E1210C89E600022841 /* ArrayExtensions.swift in Sources */, 1431466720DEAC220017E119 /* Security.swift in Sources */, 1431468720DFA58E0017E119 /* HexUtils.swift in Sources */, + F18C3AB8229BEDB2007C197F /* ScannedLocalDevicesVC.swift in Sources */, F1F339572296703C000F53A0 /* wifi_scan.pb.swift in Sources */, + F18C3ABF229BF4D4007C197F /* SSDPDiscovery.swift in Sources */, 143146B320EB22470017E119 /* ProvisionLandingViewController.swift in Sources */, 1431468B20E37B980017E119 /* Session.swift in Sources */, 143146AA20EA29E90017E119 /* LoginWithAmazonViewController.swift in Sources */, @@ -856,12 +945,13 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = Y9ZJ436PPN; + DEVELOPMENT_TEAM = QWXF6GB4AV; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", ); INFOPLIST_FILE = EspressifProvision/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -884,12 +974,13 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = Y9ZJ436PPN; + DEVELOPMENT_TEAM = QWXF6GB4AV; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", ); INFOPLIST_FILE = EspressifProvision/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1055,12 +1146,13 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = Y9ZJ436PPN; + DEVELOPMENT_TEAM = QWXF6GB4AV; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", ); INFOPLIST_FILE = EspressifProvision/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1179,12 +1271,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = Y9ZJ436PPN; + DEVELOPMENT_TEAM = QWXF6GB4AV; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", ); INFOPLIST_FILE = EspressifProvision/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1308,12 +1401,13 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = Y9ZJ436PPN; + DEVELOPMENT_TEAM = QWXF6GB4AV; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", ); INFOPLIST_FILE = EspressifProvision/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1439,12 +1533,13 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = Y9ZJ436PPN; + DEVELOPMENT_TEAM = QWXF6GB4AV; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", ); INFOPLIST_FILE = EspressifProvision/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1569,12 +1664,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = Y9ZJ436PPN; + DEVELOPMENT_TEAM = QWXF6GB4AV; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", ); INFOPLIST_FILE = EspressifProvision/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1698,12 +1794,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = Y9ZJ436PPN; + DEVELOPMENT_TEAM = QWXF6GB4AV; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", ); INFOPLIST_FILE = EspressifProvision/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1827,12 +1924,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = Y9ZJ436PPN; + DEVELOPMENT_TEAM = QWXF6GB4AV; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", ); INFOPLIST_FILE = EspressifProvision/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1956,12 +2054,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = Y9ZJ436PPN; + DEVELOPMENT_TEAM = QWXF6GB4AV; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", ); INFOPLIST_FILE = EspressifProvision/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -2086,12 +2185,13 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = Y9ZJ436PPN; + DEVELOPMENT_TEAM = QWXF6GB4AV; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", ); INFOPLIST_FILE = EspressifProvision/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/EspressifProvision/EspressifProvision/Assets.xcassets/wifi_symbol.imageset/Contents.json b/EspressifProvision/EspressifProvision/Assets.xcassets/alexa_logo.imageset/Contents.json similarity index 61% rename from EspressifProvision/EspressifProvision/Assets.xcassets/wifi_symbol.imageset/Contents.json rename to EspressifProvision/EspressifProvision/Assets.xcassets/alexa_logo.imageset/Contents.json index 0944f71..1051605 100644 --- a/EspressifProvision/EspressifProvision/Assets.xcassets/wifi_symbol.imageset/Contents.json +++ b/EspressifProvision/EspressifProvision/Assets.xcassets/alexa_logo.imageset/Contents.json @@ -2,15 +2,17 @@ "images" : [ { "idiom" : "universal", - "filename" : "wifi_symbol.png", + "filename" : "vertical_RGB_color_darktext.png", "scale" : "1x" }, { "idiom" : "universal", + "filename" : "vertical_RGB_color_darktext-1.png", "scale" : "2x" }, { "idiom" : "universal", + "filename" : "vertical_RGB_color_darktext-2.png", "scale" : "3x" } ], diff --git a/EspressifProvision/EspressifProvision/Assets.xcassets/alexa_logo.imageset/vertical_RGB_color_darktext-1.png b/EspressifProvision/EspressifProvision/Assets.xcassets/alexa_logo.imageset/vertical_RGB_color_darktext-1.png new file mode 100644 index 0000000..5b30877 Binary files /dev/null and b/EspressifProvision/EspressifProvision/Assets.xcassets/alexa_logo.imageset/vertical_RGB_color_darktext-1.png differ diff --git a/EspressifProvision/EspressifProvision/Assets.xcassets/alexa_logo.imageset/vertical_RGB_color_darktext-2.png b/EspressifProvision/EspressifProvision/Assets.xcassets/alexa_logo.imageset/vertical_RGB_color_darktext-2.png new file mode 100644 index 0000000..5b30877 Binary files /dev/null and b/EspressifProvision/EspressifProvision/Assets.xcassets/alexa_logo.imageset/vertical_RGB_color_darktext-2.png differ diff --git a/EspressifProvision/EspressifProvision/Assets.xcassets/alexa_logo.imageset/vertical_RGB_color_darktext.png b/EspressifProvision/EspressifProvision/Assets.xcassets/alexa_logo.imageset/vertical_RGB_color_darktext.png new file mode 100644 index 0000000..5b30877 Binary files /dev/null and b/EspressifProvision/EspressifProvision/Assets.xcassets/alexa_logo.imageset/vertical_RGB_color_darktext.png differ diff --git a/EspressifProvision/EspressifProvision/Base.lproj/Main.storyboard b/EspressifProvision/EspressifProvision/Base.lproj/Main.storyboard index c7db7c6..dab744c 100644 --- a/EspressifProvision/EspressifProvision/Base.lproj/Main.storyboard +++ b/EspressifProvision/EspressifProvision/Base.lproj/Main.storyboard @@ -9,6 +9,14 @@ + + + AmazonEmberDisplay-Light + + + Bookerly-Italic + + @@ -71,7 +79,7 @@ - + + + + + + @@ -329,6 +357,276 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Your device includes access to Alexa. +Connect your Amazon account to access personalized features. + + + + + + + + + + + Alexa allows you to use voice to play music and get news, sports, scores, weather and more-all hands-free. +All you have to do is ask Alexa. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -403,7 +701,7 @@ - + + diff --git a/EspressifProvision/EspressifProvision/Info.plist b/EspressifProvision/EspressifProvision/Info.plist index b9c9666..ebfff1b 100644 --- a/EspressifProvision/EspressifProvision/Info.plist +++ b/EspressifProvision/EspressifProvision/Info.plist @@ -3,7 +3,7 @@ APIKey - + eyJhbGciOiJSU0EtU0hBMjU2IiwidmVyIjoiMSJ9.eyJ2ZXIiOiIzIiwiZW5kcG9pbnRzIjp7ImF1dGh6IjoiaHR0cHM6Ly93d3cuYW1hem9uLmNvbS9hcC9vYSIsInRva2VuRXhjaGFuZ2UiOiJodHRwczovL2FwaS5hbWF6b24uY29tL2F1dGgvbzIvdG9rZW4ifSwiY2xpZW50SWQiOiJhbXpuMS5hcHBsaWNhdGlvbi1vYTItY2xpZW50Ljk0NTA0YjhjZjQ0ZDQ2OTQ4YmJkNmMwYjdlNmViNTljIiwiYXBwRmFtaWx5SWQiOiJhbXpuMS5hcHBsaWNhdGlvbi45ZjA5NDkzYzQxNDI0YjczOGE0YWNmYThkNWVlN2Y3MCIsImJ1bmRsZVNlZWRJZCI6ImNvbS5lc3ByZXNzaWYuaW50cHJvdmJsZWF2cyIsImJ1bmRsZUlkIjoiY29tLmVzcHJlc3NpZi5pbnRwcm92YmxlYXZzIiwiaXNzIjoiQW1hem9uIiwidHlwZSI6IkFQSUtleSIsImFwcFZhcmlhbnRJZCI6ImFtem4xLmFwcGxpY2F0aW9uLWNsaWVudC41ZjRjZTE2MWU1MzQ0Zjk0OWU2YTVmMTA3Yzc5ZDhmNCIsInRydXN0UG9vbCI6bnVsbCwiYXBwSWQiOiJhbXpuMS5hcHBsaWNhdGlvbi1jbGllbnQuNWY0Y2UxNjFlNTM0NGY5NDllNmE1ZjEwN2M3OWQ4ZjQiLCJpZCI6IjA0MGEwNjkyLTc4ODUtMTFlOS1hM2EwLWRiYzNmZDYzMmEyZiIsImlhdCI6IjE1NTgwODQ4MzA1MjUifQ==.HiXv0UKO7zl7wZABuAkXrRhUAwa4f4nu5X2ThcDL/ZUqgRTZpWGyhwvmWKeLVYV81QcjLJaNU1lr3wWGYT9utEWvsDzMZm4eLHtnkg38n8QZZjaCPC8EO+3ExU3mU+Zs5RJHRq0we4lZypM5SCna0qKFZ5BX5D6iCgkn+l/bhHIvc8M3a3EWt6689BLVQNqQer8+wKYhG96/xXz5kH+7YMKcu0hgpp5JIeBSLcx1bOi+ymK3QWhCJPNKV1t98joBAVPI9Z1/0Qa0WW6WJ97yhRZTs7XFm8gyz6vlnUsrfBArLrfb+S2/Rz1U2eTQzzkSC9uF0LNKHGdtUYRQXKNtcw== BLEAVSConfigUUID ff54 BLEConfigUUID @@ -19,7 +19,7 @@ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName - Int BLE AVS + Int-BLE-AVS-Prov CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -31,22 +31,22 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0 + 1.1 CFBundleURLTypes CFBundleTypeRole Editor CFBundleURLName - com.espressif.avs.provisioning.ble + com.espressif.intprovbleavs CFBundleURLSchemes - amzn-com.espressif.avs.provisioning.ble + amzn-com.espressif.intprovbleavs CFBundleVersion - 1 + 2 CodeVerifier abcd1234 LSRequiresIPhoneOS diff --git a/EspressifProvision/EspressifProvision/Model/AlexaDevice.swift b/EspressifProvision/EspressifProvision/Model/AlexaDevice.swift new file mode 100644 index 0000000..346ab05 --- /dev/null +++ b/EspressifProvision/EspressifProvision/Model/AlexaDevice.swift @@ -0,0 +1,23 @@ +// +// AlexaDevice.swift +// EspressifProvision +// +// Created by Vikas Chandra on 27/05/19. +// Copyright © 2019 Espressif. All rights reserved. +// + +import Foundation + +class AlexaDevice: NSObject { + var modelNumber: String? + var hostAddress: String? + var status: String? + var softwareVersion: String? + var friendlyname: String? + var uuid: String? + + init(hostAddr: String) { + hostAddress = hostAddr + friendlyname = nil + } +} diff --git a/EspressifProvision/EspressifProvision/SSDPClient/SSDPDiscovery.swift b/EspressifProvision/EspressifProvision/SSDPClient/SSDPDiscovery.swift new file mode 100755 index 0000000..cbb4fa3 --- /dev/null +++ b/EspressifProvision/EspressifProvision/SSDPClient/SSDPDiscovery.swift @@ -0,0 +1,132 @@ +import Foundation +import Socket + +// MARK: Protocols + +/// Delegate for service discovery +public protocol SSDPDiscoveryDelegate { + /// Tells the delegate a requested service has been discovered. + func ssdpDiscovery(_ discovery: SSDPDiscovery, didDiscoverService service: SSDPService) + + /// Tells the delegate that the discovery ended due to an error. + func ssdpDiscovery(_ discovery: SSDPDiscovery, didFinishWithError error: Error) + + /// Tells the delegate that the discovery has started. + func ssdpDiscoveryDidStart(_ discovery: SSDPDiscovery) + + /// Tells the delegate that the discovery has finished. + func ssdpDiscoveryDidFinish(_ discovery: SSDPDiscovery) +} + +// public extension SSDPDiscoveryDelegate { +// func ssdpDiscovery(_: SSDPDiscovery, didDiscoverService _: SSDPService) {} +// +// func ssdpDiscovery(_: SSDPDiscovery, didFinishWithError _: Error) {} +// +// func ssdpDiscoveryDidStart(_: SSDPDiscovery) {} +// +// func ssdpDiscoveryDidFinish(_: SSDPDiscovery) {} +// } + +/// SSDP discovery for UPnP devices on the LAN +public class SSDPDiscovery { + /// The UDP socket + private var socket: Socket? + + /// Delegate for service discovery + public var delegate: SSDPDiscoveryDelegate? + + /// The client is discovering + public var isDiscovering: Bool { + return socket != nil + } + + // MARK: Initialisation + + public init() {} + + deinit { + self.stop() + } + + // MARK: Private functions + + /// Read responses. + private func readResponses() { + do { + var data = Data() + let (bytesRead, address) = try socket!.readDatagram(into: &data) + + if bytesRead > 0 { + let response = String(data: data, encoding: .utf8) + let (remoteHost, _) = Socket.hostnameAndPort(from: address!)! + delegate?.ssdpDiscovery(self, didDiscoverService: SSDPService(host: remoteHost, response: response!)) + } + + } catch { + forceStop() + delegate?.ssdpDiscovery(self, didFinishWithError: error) + } + } + + /// Read responses with timeout. + private func readResponses(forDuration duration: TimeInterval) { + let queue = DispatchQueue.global() + + queue.async { + while self.isDiscovering { + self.readResponses() + } + } + + queue.asyncAfter(deadline: .now() + duration) { [unowned self] in + self.stop() + } + } + + /// Force stop discovery closing the socket. + private func forceStop() { + if isDiscovering { + socket?.close() + } + socket = nil + } + + // MARK: Public functions + + /** + Discover SSDP services for a duration. + - Parameters: + - duration: The amount of time to wait. + - searchTarget: The type of the searched service. + */ + open func discoverService(forDuration duration: TimeInterval = 10, searchTarget: String = "ssdp:all") { + delegate?.ssdpDiscoveryDidStart(self) + + let message = "M-SEARCH * HTTP/1.1\r\n" + + "MAN: \"ssdp:discover\"\r\n" + + "HOST: 239.255.255.250:1900\r\n" + + "ST: \(searchTarget)\r\n" + "ST: ssdp:all" + "\r\n" + + "MX: \(Int(duration))\r\n\r\n" + + do { + socket = try Socket.create(type: .datagram, proto: .udp) + try socket?.listen(on: 0) + + readResponses(forDuration: duration) + try socket?.write(from: message, to: Socket.createAddress(for: "239.255.255.250", on: 1900)!) + + } catch { + forceStop() + delegate?.ssdpDiscovery(self, didFinishWithError: error) + } + } + + /// Stop the discovery before the timeout. + open func stop() { + if socket != nil { + forceStop() + delegate?.ssdpDiscoveryDidFinish(self) + } + } +} diff --git a/EspressifProvision/EspressifProvision/SSDPClient/SSDPService.swift b/EspressifProvision/EspressifProvision/SSDPClient/SSDPService.swift new file mode 100755 index 0000000..1b19e9a --- /dev/null +++ b/EspressifProvision/EspressifProvision/SSDPClient/SSDPService.swift @@ -0,0 +1,49 @@ +import Foundation + +public class SSDPService { + /// The host of service + public internal(set) var host: String + /// The value of `LOCATION` header + public internal(set) var location: String? + /// The value of `SERVER` header + public internal(set) var server: String? + /// The value of `ST` header + public internal(set) var searchTarget: String? + /// The value of `USN` header + public internal(set) var uniqueServiceName: String? + + // MARK: Initialisation + + /** + Initialize the `SSDPService` with the discovery response. + + - Parameters: + - host: The host of service + - response: The discovery response. + */ + init(host: String, response: String) { + self.host = host + location = parse(header: "LOCATION", in: response) + server = parse(header: "SERVER", in: response) + searchTarget = parse(header: "ST", in: response) + uniqueServiceName = parse(header: "USN", in: response) + } + + // MARK: Private functions + + /** + Parse the discovery response. + + - Parameters: + - header: The header to parse. + - response: The discovery response. + */ + private func parse(header: String, in response: String) -> String? { + if let range = response.range(of: "\(header): .*", options: .regularExpression) { + var value = String(response[range]) + value = value.replacingOccurrences(of: "\(header): ", with: "") + return value + } + return nil + } +} diff --git a/EspressifProvision/EspressifProvision/Utilities/Constants.swift b/EspressifProvision/EspressifProvision/Utilities/Constants.swift new file mode 100644 index 0000000..1ff7fbe --- /dev/null +++ b/EspressifProvision/EspressifProvision/Utilities/Constants.swift @@ -0,0 +1,28 @@ +// +// Constants.swift +// EspressifProvision +// +// Created by Vikas Chandra on 28/05/19. +// Copyright © 2019 Espressif. All rights reserved. +// + +import Foundation +import MBProgressHUD +import UIKit + +struct Constants { + static let friendlynameKey = "friendlyname" + static let UUIDKey = "uuid" + + // Reuse identifier + static let deviceListCellReuseIdentifier = "deviceListCell" + static let deviceDetailVCIndentifier = "deviceDetailVC" + + static func showLoader(message: String, view: UIView) { + DispatchQueue.main.async { + let loader = MBProgressHUD.showAdded(to: view, animated: true) + loader.mode = MBProgressHUDMode.indeterminate + loader.label.text = message + } + } +} diff --git a/EspressifProvision/EspressifProvision/avs/ConfigureAVS.swift b/EspressifProvision/EspressifProvision/avs/ConfigureAVS.swift index 04d2806..83db6be 100644 --- a/EspressifProvision/EspressifProvision/avs/ConfigureAVS.swift +++ b/EspressifProvision/EspressifProvision/avs/ConfigureAVS.swift @@ -106,6 +106,44 @@ class ConfigureAVS { } } + public func isLoggedIn(completionHandler: @escaping (Bool) -> Void) { + var payload = Avs_AVSConfigPayload() + payload.msg = Avs_AVSConfigMsgType.typeCmdSignInStatus + payload.cmdSigninStatus = Avs_CmdSignInStatus() + do { + let encryptedData = try security.encrypt(data: payload.serializedData()) + if let data = encryptedData { + transport.SendConfigData(path: ConfigureAVS.AVS_CONFIG_PATH, data: data) { response, error in + if response != nil, error == nil { + completionHandler(self.processAVSLoginStatus(response: response!)) + } + } + } + } catch { + print(error) + completionHandler(false) + } + } + + public func signOut(completionHandler: @escaping (Bool) -> Void) { + var payload = Avs_AVSConfigPayload() + payload.msg = Avs_AVSConfigMsgType.typeCmdSignOut + payload.cmdSigninStatus = Avs_CmdSignInStatus() + do { + let encryptedData = try security.encrypt(data: payload.serializedData()) + if let data = encryptedData { + transport.SendConfigData(path: ConfigureAVS.AVS_CONFIG_PATH, data: data) { response, error in + if response != nil, error == nil { + completionHandler(self.processAVSLoginStatus(response: response!)) + } + } + } + } catch { + print(error) + completionHandler(false) + } + } + private func createSetAVSConfigRequest(cliendId: String, authCode: String, redirectUri: String) throws -> Data? { @@ -135,6 +173,19 @@ class ConfigureAVS { return responseStatus } + private func processAVSLoginStatus(response: Data) -> Bool { + do { + if let decryptedResponse = security.decrypt(data: response) { + let statusResponse = try Avs_AVSConfigPayload(serializedData: decryptedResponse) + return statusResponse.respSigninStatus.status == .signedIn + } + } catch { + print(error) + return false + } + return false + } + private static func generateCodeChallenge(codeVerifier: String) -> String { let codeChallenge = Data(codeVerifier.bytes).sha256() return base64ToBase64url(base64: codeChallenge.base64EncodedString()) diff --git a/EspressifProvision/EspressifProvision/fonts/AmazonEmberDisplay_Lt.ttf b/EspressifProvision/EspressifProvision/fonts/AmazonEmberDisplay_Lt.ttf new file mode 100755 index 0000000..c52e715 Binary files /dev/null and b/EspressifProvision/EspressifProvision/fonts/AmazonEmberDisplay_Lt.ttf differ diff --git a/EspressifProvision/EspressifProvision/fonts/AmazonEmberDisplay_Md.ttf b/EspressifProvision/EspressifProvision/fonts/AmazonEmberDisplay_Md.ttf new file mode 100755 index 0000000..c54166f Binary files /dev/null and b/EspressifProvision/EspressifProvision/fonts/AmazonEmberDisplay_Md.ttf differ diff --git a/EspressifProvision/EspressifProvision/fonts/AmazonEmberDisplay_Rg.ttf b/EspressifProvision/EspressifProvision/fonts/AmazonEmberDisplay_Rg.ttf new file mode 100755 index 0000000..7a70e55 Binary files /dev/null and b/EspressifProvision/EspressifProvision/fonts/AmazonEmberDisplay_Rg.ttf differ diff --git a/EspressifProvision/EspressifProvision/fonts/Bookerly-Italic.ttf b/EspressifProvision/EspressifProvision/fonts/Bookerly-Italic.ttf new file mode 100644 index 0000000..68c9a81 Binary files /dev/null and b/EspressifProvision/EspressifProvision/fonts/Bookerly-Italic.ttf differ diff --git a/EspressifProvision/EspressifProvision/ui/ManageDevice/DeviceDetailViewController.swift b/EspressifProvision/EspressifProvision/ui/ManageDevice/DeviceDetailViewController.swift new file mode 100644 index 0000000..a9a6065 --- /dev/null +++ b/EspressifProvision/EspressifProvision/ui/ManageDevice/DeviceDetailViewController.swift @@ -0,0 +1,108 @@ +// +// DeviceDetailViewController.swift +// EspressifProvision +// +// Created by Vikas Chandra on 30/05/19. +// Copyright © 2019 Espressif. All rights reserved. +// + +import Foundation +import MBProgressHUD +import UIKit + +class DeviceDetailViewController: UIViewController { + var loginStatus = false + var device: AlexaDevice? + var avsConfig: ConfigureAVS? + @IBOutlet var signedInViewContainer: UIView! + @IBOutlet var signedOutViewContainer: UIView! + + override func viewDidLoad() { + let label = UILabel(frame: CGRect(x: 10, y: 0, width: 50, height: 40)) +// label.backgroundColor = .red +// label.font = UIFont.boldSystemFont(ofSize: 14) + + label.text = device?.friendlyname + label.numberOfLines = 2 + label.textColor = .black + label.sizeToFit() + label.textAlignment = .center + + navigationItem.titleView = label + } + + override func viewWillAppear(_: Bool) { + super.viewWillAppear(true) + updateUIView() + } + + @IBAction func signInAmazon(_: Any) { + Constants.showLoader(message: "Signing In", view: view) + let transport = SoftAPTransport(baseUrl: device!.hostAddress! + ":80") + let security = Security0() + let session = Session(transport: transport, security: security) + session.initialize(response: nil) { error in + guard error == nil else { + print("Error in establishing session \(error.debugDescription)") + MBProgressHUD.hide(for: self.view, animated: true) + return + } + if session.isEstablished { + let prov = Provision(session: session) + _ = prov.getAVSDeviceDetails(completionHandler: { _, error in + guard error == nil else { + print(error!) + DispatchQueue.main.async { + MBProgressHUD.hide(for: self.view, animated: true) + } + return + } + DispatchQueue.main.async { + ConfigureAVS.loginWithAmazon(completionHandler: { avsDetails, error in + if error == nil { + prov.putAVSDeviceDetails(config: avsDetails!, completionHandler: { + DispatchQueue.main.async { + self.loginStatus = true + self.updateUIView() + } + }) + } + MBProgressHUD.hide(for: self.view, animated: true) + }) + } + }) + } else { + DispatchQueue.main.async { + MBProgressHUD.hide(for: self.view, animated: true) + } + } + } + } + + @objc func signOut() { + Constants.showLoader(message: "Signing Out", view: view) + avsConfig?.signOut(completionHandler: { status in + if !status { + DispatchQueue.main.async { + self.loginStatus = false + UIView.animate(withDuration: 0.4, animations: { + self.updateUIView() + }) + MBProgressHUD.hide(for: self.view, animated: true) + } + } + }) + } + + func updateUIView() { + if loginStatus { + navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Sign Out", style: .plain, target: self, action: #selector(signOut)) + signedInViewContainer.isHidden = false + signedOutViewContainer.isHidden = true + } else { + signedInViewContainer.isHidden = true + signedOutViewContainer.isHidden = false + navigationItem.rightBarButtonItem = nil + } + } +} diff --git a/EspressifProvision/EspressifProvision/ui/ManageDevice/DeviceListTableViewCell.swift b/EspressifProvision/EspressifProvision/ui/ManageDevice/DeviceListTableViewCell.swift new file mode 100644 index 0000000..78fda6c --- /dev/null +++ b/EspressifProvision/EspressifProvision/ui/ManageDevice/DeviceListTableViewCell.swift @@ -0,0 +1,14 @@ +// +// DeviceListTableViewCell.swift +// EspressifProvision +// +// Created by Vikas Chandra on 29/05/19. +// Copyright © 2019 Espressif. All rights reserved. +// + +import Foundation +import UIKit + +class DeviceListTableViewCell: UITableViewCell { + @IBOutlet var deviceNameLabel: UILabel! +} diff --git a/EspressifProvision/EspressifProvision/ui/ManageDevice/ScannedLocalDevicesVC.swift b/EspressifProvision/EspressifProvision/ui/ManageDevice/ScannedLocalDevicesVC.swift new file mode 100644 index 0000000..db4cd16 --- /dev/null +++ b/EspressifProvision/EspressifProvision/ui/ManageDevice/ScannedLocalDevicesVC.swift @@ -0,0 +1,146 @@ +// +// ScanLocalDevices.swift +// EspressifProvision +// +// Created by Vikas Chandra on 27/05/19. +// Copyright © 2019 Espressif. All rights reserved. +// + +import Foundation +import MBProgressHUD +import UIKit + +class ScannedLocalDevicesVC: UIViewController { + @IBOutlet var tableView: UITableView! + + let ssdpDiscovery = SSDPDiscovery() + var timeInterval: Double = 3 + var retry = 3 + var searchTarget = "urn:schemas-espressif-com:service:Alexa:1" + var alexaDevices: [AlexaDevice] = [] + + override func viewDidLoad() { + ssdpDiscovery.delegate = self + tableView.tableFooterView = UIView() + tableView.isHidden = true + Constants.showLoader(message: "Scanning devices", view: view) + searchLocalDevices() + } + + @IBAction func scanDevicesAgain(_: Any) { + retry = 3 + Constants.showLoader(message: "Scanning devices", view: view) + searchLocalDevices() + } + + @objc func searchLocalDevices() { + ssdpDiscovery.discoverService(forDuration: timeInterval, searchTarget: searchTarget) + } + + func parseResponse(header: String) -> [String: String] { + var dictionary: [String: String] = [:] + for item in header.components(separatedBy: "::") { + let value = item.components(separatedBy: ":") + dictionary.updateValue(value[1], forKey: value[0]) + } + return dictionary + } + + @objc func checkNeedForReDiscovery() { + if retry != 0 { + if alexaDevices.filter({ $0.friendlyname == nil }).count > 0 { + retry -= 1 + searchLocalDevices() + } else { + ssdpDiscovery.stop() + alexaDevices = alexaDevices.filter { $0.friendlyname != nil } + MBProgressHUD.hide(for: view, animated: true) + tableView.isHidden = false + tableView.reloadData() + } + } else { + alexaDevices = alexaDevices.filter { $0.friendlyname != nil } + MBProgressHUD.hide(for: view, animated: true) + tableView.isHidden = false + tableView.reloadData() + } + } + + func showDeviceDetails(device: AlexaDevice, avsConfig: ConfigureAVS, loginStatus: Bool = false) { + DispatchQueue.main.async { + let deviceDetailVC = self.storyboard?.instantiateViewController(withIdentifier: Constants.deviceDetailVCIndentifier) as! DeviceDetailViewController + deviceDetailVC.avsConfig = avsConfig + deviceDetailVC.loginStatus = loginStatus + deviceDetailVC.device = device + self.navigationController?.pushViewController(deviceDetailVC, animated: true) + } + } +} + +extension ScannedLocalDevicesVC: SSDPDiscoveryDelegate { + func ssdpDiscovery(_: SSDPDiscovery, didDiscoverService service: SSDPService) { + let dictionary = parseResponse(header: service.uniqueServiceName ?? "") + if dictionary.keys.contains(Constants.UUIDKey) { + let uuid = dictionary[Constants.UUIDKey] + let newDevice = AlexaDevice(hostAddr: service.host) + newDevice.uuid = uuid + let stDictionary = parseResponse(header: service.searchTarget ?? "") + if stDictionary.keys.contains(Constants.friendlynameKey) { + if let found = alexaDevices.firstIndex(where: { $0.uuid == uuid }) { + alexaDevices.remove(at: found) + } + newDevice.friendlyname = stDictionary[Constants.friendlynameKey] + alexaDevices.append(newDevice) + } else { + if !alexaDevices.contains(where: { $0.uuid == uuid }) { + alexaDevices.append(newDevice) + } + } + } + } + + func ssdpDiscovery(_: SSDPDiscovery, didFinishWithError error: Error) { + print(error) + } + + func ssdpDiscoveryDidStart(_: SSDPDiscovery) {} + + func ssdpDiscoveryDidFinish(_: SSDPDiscovery) { + performSelector(onMainThread: #selector(checkNeedForReDiscovery), with: nil, waitUntilDone: true) + } +} + +extension ScannedLocalDevicesVC: UITableViewDelegate { + func tableView(_: UITableView, heightForRowAt _: IndexPath) -> CGFloat { + return 60.0 + } + + func tableView(_: UITableView, didSelectRowAt indexPath: IndexPath) { + let alexaDevice = alexaDevices[indexPath.row] + let transport = SoftAPTransport(baseUrl: alexaDevice.hostAddress! + ":80") + let security = Security0() + let session = Session(transport: transport, security: security) + session.initialize(response: nil) { error in + guard error == nil else { + print("Error in establishing session \(error.debugDescription)") + return + } + let avsConfig = ConfigureAVS(session: session) + avsConfig.isLoggedIn(completionHandler: { status in + self.showDeviceDetails(device: alexaDevice, avsConfig: avsConfig, loginStatus: status) + }) + } + } +} + +extension ScannedLocalDevicesVC: UITableViewDataSource { + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: Constants.deviceListCellReuseIdentifier, for: indexPath) as! DeviceListTableViewCell + cell.deviceNameLabel.text = "\(alexaDevices[indexPath.row].friendlyname ?? "") | \(alexaDevices[indexPath.row].hostAddress ?? "")" + return cell + } + + func tableView(_: UITableView, numberOfRowsInSection _: Int) -> Int { + return alexaDevices.count + } +} diff --git a/EspressifProvision/Podfile b/EspressifProvision/Podfile index 66ee92a..5f4a006 100644 --- a/EspressifProvision/Podfile +++ b/EspressifProvision/Podfile @@ -10,6 +10,7 @@ abstract_target 'EspressifProvisionAll' do pod 'SwiftProtobuf', '~> 1.5.0' pod 'Curve25519', '~> 1.1.0' pod 'MBProgressHUD', '~> 1.1.0' + pod 'BlueSocket' target 'EspressifProvision' target 'EspressifProvisionTests' do diff --git a/proto/avsconfig.proto b/proto/avsconfig.proto index 1ec6d1c..ea53343 100644 --- a/proto/avsconfig.proto +++ b/proto/avsconfig.proto @@ -6,6 +6,8 @@ enum AVSConfigStatus { Success = 0; InvalidParam = 1; InvalidState = 2; + SignedIn = 3; + SignedOut = 4; } message CmdGetDetails { @@ -30,11 +32,31 @@ message RespSetConfig{ uint32 Dummy = 2; } +message CmdSignInStatus { + uint32 Dummy = 1; +} + +message RespSignInStatus { + AVSConfigStatus Status = 1; +} + +message CmdSignOut { + uint32 Dummy = 1; +} + +message RespSignOut { + AVSConfigStatus Status = 1; +} + enum AVSConfigMsgType { TypeCmdGetDetails = 0; TypeRespGetDetails = 1; TypeCmdSetConfig = 2; TypeRespSetConfig =3; + TypeCmdSignInStatus = 4; + TypeRespSignInStatus = 5; + TypeCmdSignOut = 6; + TypeRespSignOut = 7; } message AVSConfigPayload { @@ -44,5 +66,9 @@ message AVSConfigPayload { RespGetDetails resp_get_details = 11; CmdSetConfig cmd_set_config = 12; RespSetConfig resp_set_config = 13; + CmdSignInStatus cmd_signin_status = 14; + RespSignInStatus resp_signin_status = 15; + CmdSignOut cmd_sign_out = 16; + RespSignOut resp_sign_out = 17; } } \ No newline at end of file