You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
6.7 KiB
Swift
190 lines
6.7 KiB
Swift
//
|
|
// HMG_Geofence.swift
|
|
// Runner
|
|
//
|
|
// Created by ZiKambrani on 13/12/2020.
|
|
//
|
|
|
|
import UIKit
|
|
import CoreLocation
|
|
|
|
fileprivate var df = DateFormatter()
|
|
fileprivate var transition = ""
|
|
|
|
enum Transition:Int {
|
|
case entry = 1
|
|
case exit = 2
|
|
func name() -> String{
|
|
return self.rawValue == 1 ? "Enter" : "Exit"
|
|
}
|
|
}
|
|
|
|
class HMG_Geofence:NSObject{
|
|
|
|
var geoZones:[GeoZoneModel]?
|
|
var locationManager:CLLocationManager!{
|
|
didSet{
|
|
// https://developer.apple.com/documentation/corelocation/cllocationmanager/1423531-startmonitoringsignificantlocati
|
|
|
|
locationManager.allowsBackgroundLocationUpdates = true
|
|
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
|
|
locationManager.activityType = .other
|
|
locationManager.delegate = self
|
|
locationManager.requestAlwaysAuthorization()
|
|
// locationManager.distanceFilter = 500
|
|
// locationManager.startMonitoringSignificantLocationChanges()
|
|
}
|
|
}
|
|
|
|
private static var shared_:HMG_Geofence?
|
|
class func shared() -> HMG_Geofence{
|
|
if HMG_Geofence.shared_ == nil{
|
|
HMG_Geofence.initGeofencing()
|
|
}
|
|
return shared_!
|
|
}
|
|
|
|
class func initGeofencing(){
|
|
shared_ = HMG_Geofence()
|
|
shared_?.locationManager = CLLocationManager()
|
|
}
|
|
|
|
func register(geoZones:[GeoZoneModel]){
|
|
|
|
self.geoZones = geoZones
|
|
|
|
let monitoredRegions_ = monitoredRegions()
|
|
self.geoZones?.forEach({ (zone) in
|
|
if let region = zone.toRegion(locationManager: locationManager){
|
|
if let already = monitoredRegions_.first(where: {$0.identifier == zone.identifier()}){
|
|
debugPrint("Already monitering region: \(already)")
|
|
}else{
|
|
startMonitoring(region: region)
|
|
}
|
|
}else{
|
|
debugPrint("Invalid region: \(zone.latitude ?? "invalid_latitude"),\(zone.longitude ?? "invalid_longitude"),r\(zone.radius ?? 0) | \(zone.identifier())")
|
|
}
|
|
})
|
|
}
|
|
|
|
func monitoredRegions() -> Set<CLRegion>{
|
|
return locationManager.monitoredRegions
|
|
}
|
|
|
|
func unRegisterAll(){
|
|
for region in locationManager.monitoredRegions {
|
|
locationManager.stopMonitoring(for: region)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// CLLocationManager Delegates
|
|
extension HMG_Geofence : CLLocationManagerDelegate{
|
|
|
|
func startMonitoring(region: CLCircularRegion) {
|
|
if !CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) {
|
|
return
|
|
}
|
|
|
|
if CLLocationManager.authorizationStatus() != .authorizedAlways {
|
|
let message = """
|
|
Your geotification is saved but will only be activated once you grant
|
|
HMG permission to access the device location.
|
|
"""
|
|
debugPrint(message)
|
|
}
|
|
|
|
locationManager.startMonitoring(for: region)
|
|
locationManager.requestState(for: region)
|
|
debugPrint("Starts monitering region: \(region)")
|
|
}
|
|
|
|
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
|
|
debugPrint("didEnterRegion: \(region)")
|
|
if region is CLCircularRegion {
|
|
handleEvent(for: region,transition: .entry, location: manager.location)
|
|
}
|
|
}
|
|
|
|
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
|
|
debugPrint("didExitRegion: \(region)")
|
|
if region is CLCircularRegion {
|
|
handleEvent(for: region,transition: .exit, location: manager.location)
|
|
}
|
|
}
|
|
|
|
func locationManager(_ manager: CLLocationManager, didDetermineState state: CLRegionState, for region: CLRegion) {
|
|
debugPrint("didDetermineState: \(state)")
|
|
}
|
|
|
|
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
|
debugPrint("didUpdateLocations: \(locations)")
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// Helpers
|
|
extension HMG_Geofence{
|
|
|
|
func handleEvent(for region: CLRegion!, transition:Transition, location:CLLocation?) {
|
|
notifyUser(forRegion: region, transition: transition, location: locationManager.location)
|
|
notifyServer(forRegion: region, transition: transition, location: locationManager.location)
|
|
}
|
|
|
|
func geoZone(by id: String) -> GeoZoneModel? {
|
|
var zone:GeoZoneModel? = nil
|
|
if let zones_ = geoZones{
|
|
zone = zones_.first(where: { $0.identifier() == id})
|
|
}else{
|
|
// let jsonArray = UserDefaults.standard.string(forKey: "hmg-geo-fences")
|
|
}
|
|
return zone
|
|
}
|
|
|
|
|
|
func notifyUser(forRegion:CLRegion, transition:Transition, location:CLLocation?){
|
|
if let zone = geoZone(by: forRegion.identifier){
|
|
if UIApplication.shared.applicationState == .active {
|
|
mainViewController.showAlert(withTitle: transition.name(), message: zone.message())
|
|
}else{
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
func notifyServer(forRegion:CLRegion, transition:Transition, location:CLLocation?){
|
|
df.dateFormat = "MMM/dd/yyyy hh:mm:ss"
|
|
if let userProfileJson = UserDefaults.standard.string(forKey: "flutter.user-profile"),
|
|
let userProfile = dictionary(from: userProfileJson), let patientId = userProfile["PatientID"] as? Int{
|
|
|
|
if let idString = forRegion.identifier.split(separator: "_").first, let idInt = Int(idString){
|
|
let body:[String:Any] = [
|
|
"PointsID":idInt,
|
|
"GeoType":transition.rawValue,
|
|
"PatientID":patientId
|
|
]
|
|
|
|
let url = "https://hmgwebservices.com/Services/Patients.svc/REST/GeoF_InsertPatientFileInfo"
|
|
httpPostRequest(urlString: url, jsonBody: body){ (status,json) in
|
|
let status_ = status ? "Notified" : "Not notified"
|
|
showNotification(title: transition.name(), subtitle: forRegion.identifier, message: status_)
|
|
|
|
|
|
var logs = UserDefaults.init(suiteName: "GeoFenceLog")?.dictionary(forKey: "LOGS") ?? [:]
|
|
if var geo = logs[forRegion.identifier] as? [String]{
|
|
geo.append("\(status_) at \(df.string(from: Date()))")
|
|
}else{
|
|
logs.updateValue(["\(status_) at \(df.string(from: Date()))"], forKey: forRegion.identifier)
|
|
}
|
|
|
|
UserDefaults.init(suiteName: "GeoFenceLog")?.set(logs, forKey: "LOGS")
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|