From 5d2ff791a92c6b5e76758cac0146af6121d1ad22 Mon Sep 17 00:00:00 2001 From: Orlando Aliaga Date: Mon, 21 Nov 2022 17:59:36 -0300 Subject: [PATCH] Geofencing event is sent Geofencing event is sent --- Prey.xcodeproj/project.pbxproj | 11 ++- .../UserInterfaceState.xcuserstate | Bin 111234 -> 111234 bytes Prey/Classes/Geofencing.swift | 41 ++++++++- Prey/Classes/PreyAction.swift | 7 +- Prey/Classes/PreyDevice.swift | 9 +- Prey/Classes/PreyHTTPResponse.swift | 48 +++++++--- Prey/GeofencingLocation.swift | 82 ++++++++++++++++++ 7 files changed, 181 insertions(+), 17 deletions(-) create mode 100644 Prey/GeofencingLocation.swift diff --git a/Prey.xcodeproj/project.pbxproj b/Prey.xcodeproj/project.pbxproj index 3d12336..49b2209 100644 --- a/Prey.xcodeproj/project.pbxproj +++ b/Prey.xcodeproj/project.pbxproj @@ -122,6 +122,7 @@ 3BFF00801D3E7EAC00BEF7E0 /* PreyDeployment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BFF007F1D3E7EAC00BEF7E0 /* PreyDeployment.swift */; }; 3BFF00841D3E8A2400BEF7E0 /* AppFeedback.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3BFF00811D3E8A2400BEF7E0 /* AppFeedback.plist */; }; 3BFF00861D3E8A2400BEF7E0 /* ManagedAppConfig.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3BFF00831D3E8A2400BEF7E0 /* ManagedAppConfig.plist */; }; + 74C856A3292318DC0053EB6A /* GeofencingLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74C856A2292318DC0053EB6A /* GeofencingLocation.swift */; }; C7A403C34BB1520215CE478D /* Pods_PreyTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8392F72CF9DA4F14F65199F9 /* Pods_PreyTests.framework */; }; DD5CB5EF9D81A896E21B4D60 /* Pods_PreyNotify.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C384AA2935BAE7631E3DDAC /* Pods_PreyNotify.framework */; }; /* End PBXBuildFile section */ @@ -297,6 +298,7 @@ 3BFF00821D3E8A2400BEF7E0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Plist/Info.plist; sourceTree = ""; }; 3BFF00831D3E8A2400BEF7E0 /* ManagedAppConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = ManagedAppConfig.plist; path = Plist/ManagedAppConfig.plist; sourceTree = ""; }; 635174AA098F25D2F1D8BC05 /* Pods-Prey.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Prey.release.xcconfig"; path = "Target Support Files/Pods-Prey/Pods-Prey.release.xcconfig"; sourceTree = ""; }; + 74C856A2292318DC0053EB6A /* GeofencingLocation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeofencingLocation.swift; sourceTree = ""; }; 8392F72CF9DA4F14F65199F9 /* Pods_PreyTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PreyTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9BF340641AA1FFAA199E2B03 /* Pods-PreyTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PreyTests.release.xcconfig"; path = "Target Support Files/Pods-PreyTests/Pods-PreyTests.release.xcconfig"; sourceTree = ""; }; 9D026084F779D119866C4642 /* Pods-PreyNotify.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PreyNotify.debug.xcconfig"; path = "Target Support Files/Pods-PreyNotify/Pods-PreyNotify.debug.xcconfig"; sourceTree = ""; }; @@ -555,6 +557,7 @@ 3B38BA921D231B1C00B6799B /* Detach.swift */, 3B33A76320F69D0B00F3B64E /* Battery.swift */, 3BDA80D821120DE4003B028C /* FileRetrieval.swift */, + 74C856A2292318DC0053EB6A /* GeofencingLocation.swift */, ); name = "Prey Modules"; sourceTree = ""; @@ -743,6 +746,7 @@ }; 3B8283FE199198E6000E4545 = { CreatedOnToolsVersion = 6.0; + DevelopmentTeam = M2J57RQ35B; LastSwiftMigration = 1020; TestTargetID = 3B8283EC199198E6000E4545; }; @@ -872,6 +876,7 @@ "${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework", "${BUILT_PRODUCTS_DIR}/FirebaseCrashlytics/FirebaseCrashlytics.framework", "${BUILT_PRODUCTS_DIR}/FirebaseInstallations/FirebaseInstallations.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseMessaging/FirebaseMessaging.framework", "${BUILT_PRODUCTS_DIR}/GoogleDataTransport/GoogleDataTransport.framework", "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework", @@ -884,6 +889,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCrashlytics.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessaging.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleDataTransport.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework", @@ -1020,6 +1026,7 @@ 3B42A2691D25A9EA002848C0 /* PreyProtocol.swift in Sources */, 3BDF988120338AC70023D4AA /* HomeWebVC.swift in Sources */, 3B8629911EF03CB400BE92D4 /* Errno.swift in Sources */, + 74C856A3292318DC0053EB6A /* GeofencingLocation.swift in Sources */, 3B41BDAE1D05FF9F003DF0CE /* GeofenceZones+Class.swift in Sources */, 3BFF00801D3E7EAC00BEF7E0 /* PreyDeployment.swift in Sources */, 3B86299B1EF03CB400BE92D4 /* Socket+File.swift in Sources */, @@ -1306,7 +1313,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Prey.app/Prey"; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = M2J57RQ35B; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -1330,7 +1337,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Prey.app/Prey"; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = M2J57RQ35B; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = PreyTests/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Prey; diff --git a/Prey.xcworkspace/xcuserdata/oso.xcuserdatad/UserInterfaceState.xcuserstate b/Prey.xcworkspace/xcuserdata/oso.xcuserdatad/UserInterfaceState.xcuserstate index 5f00c65f922d47d3671b8287cf70bc7948c5d42a..c593c6d42c3df837286ba10ce059d665d4b9e229 100644 GIT binary patch delta 62 zcmZpA%GUIhZG)8x%g&;gW}EF)M0Git{;}ybd~0NUIC(;#baQ#&_VPf+U2?pU3=DxW PK%5A~$=mG;7+stI=!6wJ delta 70 zcmZpA%GUIhZG)8x%dF|IR5#nHi0TTm=`#ImWPI50Z4qk&Gh-v;=E)z=3OAPrZZ8jH Y+$F~w#lR341H_3yoU+}nfYHSX0JO#!ZvX%Q diff --git a/Prey/Classes/Geofencing.swift b/Prey/Classes/Geofencing.swift index fd44c64..f4fb417 100644 --- a/Prey/Classes/Geofencing.swift +++ b/Prey/Classes/Geofencing.swift @@ -10,12 +10,13 @@ import Foundation import CoreData import CoreLocation -class Geofencing: PreyAction, CLLocationManagerDelegate { +class Geofencing: PreyAction, CLLocationManagerDelegate, LocationGeoServiceDelegate { // MARK: Properties let geoManager = CLLocationManager() + var geofencingLocation = GeofencingLocation() // MARK: Functions @@ -34,10 +35,18 @@ class Geofencing: PreyAction, CLLocationManagerDelegate { let localZonesArray = PreyCoreData.sharedInstance.getCurrentGeofenceZones() PreyLogger("ZONES") + geofencingLocation.stopLocation() // Added zones events if let addedZones = getAddedZones(response, withLocalZones: localZonesArray) { sendEventToPanel(addedZones, withCommand:kCommand.start , withStatus:kStatus.started) + var zonesId = [NSNumber]() + for itemAdded in addedZones { + zonesId.append(itemAdded.id!) + } + geofencingLocation.waitForRequest = true + geofencingLocation.delegate = self + geofencingLocation.startLocation(zones:zonesId) } // Deleted zones events @@ -261,4 +270,34 @@ class Geofencing: PreyAction, CLLocationManagerDelegate { } return geofenceZoneItem } + + // Location received + func locationReceived(_ location:[CLLocation],_ zonesId:[NSNumber]) { + let localZonesArray = PreyCoreData.sharedInstance.getCurrentGeofenceZones() + for localZone:GeofenceZones in localZonesArray { + for id in zonesId { + if(id == localZone.id){ + if let loc = location.first { + var zoneId = localZone.id!.stringValue + let dbLat = Double(localZone.lat!) + let dbLong = Double(localZone.lng!) + let location = CLLocation(latitude: dbLat, longitude: dbLong) + let distance = location.distance(from: loc) + let radius = Double(localZone.radius!) + var withZoneInfo = kGeofence.IN.rawValue + if(distance >= radius){ + withZoneInfo=kGeofence.OUT.rawValue + } + let center_lat = Double(loc.coordinate.latitude) + let center_lon = Double(loc.coordinate.longitude) + let center = CLLocationCoordinate2DMake(center_lat, center_lon) + let regionIn:CLCircularRegion = CLCircularRegion(center: center, radius: radius, identifier: zoneId) + sleep(1) + let params = GeofencingManager.sharedInstance.getParamteresToSend(regionIn, withZoneInfo: withZoneInfo) + GeofencingManager.sharedInstance.sendNotifyToPanel(params,toEndpoint:eventsDeviceEndpoint) + } + } + } + } + } } diff --git a/Prey/Classes/PreyAction.swift b/Prey/Classes/PreyAction.swift index 46343aa..d64fe6c 100644 --- a/Prey/Classes/PreyAction.swift +++ b/Prey/Classes/PreyAction.swift @@ -135,7 +135,12 @@ class PreyAction : Operation { func checkGeofenceZones(_ action:Geofencing) { // Check userApiKey isn't empty if let username = PreyConfig.sharedInstance.userApiKey { - PreyHTTPClient.sharedInstance.userRegisterToPrey(username, password:"x", params:nil, messageId:nil, httpMethod:Method.GET.rawValue, endPoint:geofencingEndpoint, onCompletion:PreyHTTPResponse.checkResponse(RequestType.geofenceZones, preyAction:action, onCompletion:{(isSuccess: Bool) in PreyLogger("Request geofencesZones")})) + PreyHTTPClient.sharedInstance.userRegisterToPrey(username, password:"x", params:nil, messageId:nil, httpMethod:Method.GET.rawValue, endPoint:geofencingEndpoint, onCompletion:PreyHTTPResponse.checkResponse(RequestType.geofenceZones, preyAction:action, onCompletion:{ + (isSuccess: Bool) in PreyLogger("Request geofencesZones:\(isSuccess)") + if !isSuccess { + self.checkGeofenceZones(action) + } + })) } else { PreyLogger("Error auth check Geofence") } diff --git a/Prey/Classes/PreyDevice.swift b/Prey/Classes/PreyDevice.swift index 3187627..e10dc8c 100644 --- a/Prey/Classes/PreyDevice.swift +++ b/Prey/Classes/PreyDevice.swift @@ -98,7 +98,14 @@ class PreyDevice { class func infoDevice(_ onCompletion:@escaping (_ isSuccess: Bool) -> Void) { if let username = PreyConfig.sharedInstance.userApiKey { - PreyHTTPClient.sharedInstance.userRegisterToPrey(username, password:"x", params:nil, messageId:nil, httpMethod:Method.GET.rawValue, endPoint:infoEndpoint, onCompletion:PreyHTTPResponse.checkResponse(RequestType.infoDevice, preyAction:nil, onCompletion:onCompletion)) + PreyHTTPClient.sharedInstance.userRegisterToPrey(username, password:"x", params:nil, messageId:nil, httpMethod:Method.GET.rawValue, endPoint:infoEndpoint, onCompletion:PreyHTTPResponse.checkResponse(RequestType.infoDevice, preyAction:nil, onCompletion:{ + (isSuccess: Bool) in PreyLogger("Request: infoDevice") + if !isSuccess { + infoDevice({(isSuccess: Bool) in + PreyLogger("infoDevice isSuccess:\(isSuccess)") + }) + } + })) }else{ PreyLogger("Error infoDevice") } diff --git a/Prey/Classes/PreyHTTPResponse.swift b/Prey/Classes/PreyHTTPResponse.swift index b3d29c7..68a281f 100644 --- a/Prey/Classes/PreyHTTPResponse.swift +++ b/Prey/Classes/PreyHTTPResponse.swift @@ -68,7 +68,9 @@ class PreyHTTPResponse { checkActionDevice(isResponseSuccess, withData:data, withError:error, statusCode:code) case .geofenceZones: - checkGeofenceZones(isResponseSuccess, withAction:action, withData:data, withError:error, statusCode:code) + let out=checkGeofenceZones(isResponseSuccess, withAction:action, withData:data, withError:error, statusCode:code) + onCompletion(out) + return case .trigger: checkTrigger(isResponseSuccess, withAction:action, withData:data, withError:error, statusCode:code) @@ -84,8 +86,11 @@ class PreyHTTPResponse { case .statusDevice: checkStatusDevice(isResponseSuccess, withAction:action, withData:data, withError:error, statusCode:code) + case .infoDevice: - checkInfoDevice(isResponseSuccess, withAction:action, withData:data, withError:error, statusCode:code) + let out=checkInfoDevice(isResponseSuccess, withAction:action, withData:data, withError:error, statusCode:code) + onCompletion(out) + return } @@ -366,38 +371,52 @@ class PreyHTTPResponse { PreyNotification.sharedInstance.checkRequestVerificationSucceded(false) } } - + // Check add device response - class func checkGeofenceZones(_ isSuccess:Bool, withAction action:PreyAction?, withData data:Data?, withError error:Error?, statusCode:Int?) { - + class func checkGeofenceZones(_ isSuccess:Bool, withAction action:PreyAction?, withData data:Data?, withError error:Error?, statusCode:Int?) ->Bool{ + do { + guard let dataResponse = data else { + return true + } + let str = String(decoding: dataResponse, as: UTF8.self) + guard let jsonObject: String = String(data:dataResponse, encoding:String.Encoding.utf8) else { + PreyConfig.sharedInstance.reportError("GeofenceZonesJson", statusCode: statusCode, errorDescription: "GeofenceZonesJson error") + PreyLogger("Error reading json data") + return false + } + } catch let error { + PreyConfig.sharedInstance.reportError(error) + PreyLogger("json error: \(error.localizedDescription)") + return false + } guard isSuccess else { // Check error with URLSession request guard error == nil else { PreyConfig.sharedInstance.reportError(error) PreyLogger("PreyGeofenceZones error") - return + return false } PreyConfig.sharedInstance.reportError("GeofenceZones", statusCode: statusCode, errorDescription: "GeofenceZones error") PreyLogger("Failed data send") - return + return false } // === Success guard let dataResponse = data else { PreyConfig.sharedInstance.reportError("GeofenceZonesRequest", statusCode: statusCode, errorDescription: "GeofenceZonesRequest error") PreyLogger("Errod reading request data") - return + return false } guard let jsonObject: String = String(data:dataResponse, encoding:String.Encoding.utf8) else { PreyConfig.sharedInstance.reportError("GeofenceZonesJson", statusCode: statusCode, errorDescription: "GeofenceZonesJson error") PreyLogger("Error reading json data") - return + return false } // Convert actionsArray from String to NSData guard let jsonData: Data = jsonObject.data(using: String.Encoding.utf8) else { PreyConfig.sharedInstance.reportError("GeofenceZonesObject", statusCode: statusCode, errorDescription: "GeofenceZonesObject error") PreyLogger("Error jsonObject to NSData") - return + return false } // Convert NSData to NSArray do { @@ -405,9 +424,11 @@ class PreyHTTPResponse { if let geofencingAction = action as? Geofencing { geofencingAction.updateGeofenceZones(jsonArray) } + return true } catch let error { PreyConfig.sharedInstance.reportError(error) PreyLogger("json error: \(error.localizedDescription)") + return false } } @@ -592,19 +613,22 @@ class PreyHTTPResponse { } } - class func checkInfoDevice(_ isSuccess:Bool, withAction action:PreyAction?, withData data:Data?, withError error:Error?, statusCode:Int?) { + class func checkInfoDevice(_ isSuccess:Bool, withAction action:PreyAction?, withData data:Data?, withError error:Error?, statusCode:Int?) ->Bool{ do { guard let dataResponse = data else { - return + return true } + let str = String(decoding: dataResponse, as: UTF8.self) let jsonObject = try JSONSerialization.jsonObject(with: dataResponse, options:JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary if let nameDevice = jsonObject.object(forKey: "name") as? String { PreyConfig.sharedInstance.nameDevice = nameDevice PreyConfig.sharedInstance.saveValues() } + return true } catch let error { PreyLogger("json error: \(error.localizedDescription)") + return false } } } diff --git a/Prey/GeofencingLocation.swift b/Prey/GeofencingLocation.swift new file mode 100644 index 0000000..58fe439 --- /dev/null +++ b/Prey/GeofencingLocation.swift @@ -0,0 +1,82 @@ +// +// GeofencingLocation.swift +// Prey +// +// Created by Orlando Aliaga on 14/11/2022. +// Copyright © 2022 Prey, Inc. All rights reserved. +// + +import Foundation +import CoreLocation + +protocol LocationGeoServiceDelegate { + func locationReceived(_ location:[CLLocation],_ zones:[NSNumber]) +} + +class GeofencingLocation: NSObject, CLLocationManagerDelegate { + + // MARK: Properties + + var waitForRequest = false + + let locManager = CLLocationManager() + + var delegate: LocationGeoServiceDelegate? + + var zonesId = [NSNumber]() + // MARK: Functions + + // Start Location + func startLocation( zones:[NSNumber]) { + zonesId=zones + locManager.delegate = self + locManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation + locManager.startUpdatingLocation() + locManager.pausesLocationUpdatesAutomatically = false + + if #available(iOS 9.0, *) { + locManager.allowsBackgroundLocationUpdates = true + } + } + + // Stop Location + func stopLocation() { + locManager.stopUpdatingLocation() + locManager.delegate = nil + } + + // MARK: CLLocationManagerDelegate + + // Did Update Locations + func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + PreyLogger("New location received on GeofencingLocation") + + if !waitForRequest { + return + } + + // Check if location is cached + let locationTime = abs((locations.first?.timestamp.timeIntervalSinceNow)! as Double) + if locationTime > 5 { + return + } + + guard let locate = locations.first else { + return + } + + if locate.horizontalAccuracy < 0 { + return + } + + if locate.horizontalAccuracy <= 500 { + self.delegate!.locationReceived(locations, zonesId) + stopLocation() + } + } + + // Did fail with error + func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { + PreyLogger("Error getting location: \(error.localizedDescription)") + } +}