Created
January 20, 2017 14:53
-
-
Save macropok/3df8ba519163d6e66d1de3b9819d49bd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// CirrentService.swift | |
// Cirrent_New | |
import Foundation | |
import UIKit | |
import Darwin | |
import SystemConfiguration.CaptiveNetwork | |
import CoreLocation | |
class CirrentService : NSObject { | |
open static let sharedService:CirrentService = CirrentService() | |
public var softApSSID:String { | |
get { | |
let ssid = UserDefaults.standard.string(forKey: Constants.SOFTAP_SSID_KEY) | |
if ssid == nil { | |
return "wcm-softap" | |
} | |
return ssid! | |
} | |
set(ssid) { | |
UserDefaults.standard.set(ssid, forKey: Constants.SOFTAP_SSID_KEY) | |
} | |
} | |
public var model:Model? = nil | |
public override init() { | |
super.init() | |
} | |
public func setAppIdentifier(identifier:String = "") -> String? { | |
if identifier == "" { | |
let uuid = UserDefaults.standard.string(forKey: Constants.APPID_KEY) | |
if uuid == nil || uuid == "" { | |
var uuid = UIDevice.current.identifierForVendor?.uuidString | |
if uuid == nil || uuid == "" { | |
uuid = generateUUID() | |
} | |
} | |
UserDefaults.standard.set(uuid!, forKey: Constants.APPID_KEY) | |
return uuid | |
} | |
else { | |
UserDefaults.standard.set(identifier, forKey: Constants.APPID_KEY) | |
return identifier | |
} | |
} | |
public func setAuthToken(token:String, tokenScope:String) { | |
if tokenScope == APIService.MANAGE_TOKEN_SCOPE { | |
APIService.sharedService.manage_token = token | |
} | |
else if tokenScope == APIService.SEARCH_TOKEN_SCOPE { | |
APIService.sharedService.search_token = token | |
} | |
else { | |
APIService.sharedService.bind_token = token | |
} | |
} | |
public func registerSoftApNotification(observer:Any, softApSelector:Selector) { | |
let softApNotify = Notification.Name(Constants.SOFTAP_NOTIFICATION_NAME) | |
NotificationCenter.default.addObserver(observer, selector: softApSelector, name: softApNotify, object: nil) | |
} | |
private var findDeviceTimer:Timer? = nil | |
public func findDevice(completion: @escaping FindDeviceCompletionHandler) { | |
_ = setAppIdentifier() | |
initModel() | |
if (model!.ssid == nil || model!.bssid == nil) && isOnCellularNetwork() == false { | |
LogService.sharedService.debug(data: "Find Devices Failed - NETWORK OFFLINE") | |
completion(FIND_DEVICE_RESULT.FAILED_NETWORK_OFFLINE, nil) | |
return | |
} | |
if CLLocationManager.locationServicesEnabled() == false { | |
LogService.sharedService.debug(data: "Find Devices Failed - LOCATION SERVICE DISABLED") | |
completion(FIND_DEVICE_RESULT.FAILED_LOCATION_DISABLED, nil) | |
return | |
} | |
self.uploadEnvironment(completion: { | |
resp in | |
if resp != RESPONSE.SUCCESS { | |
LogService.sharedService.debug(data: "Find Devices Failed - UPLOAD ENVIRONMENT FAILED") | |
completion(FIND_DEVICE_RESULT.FAILED_UPLOAD_ENVIRONMENT, nil) | |
return | |
} | |
DispatchQueue.main.async { | |
self.findNearByDevices(completion: { | |
result, devices in | |
if result != FIND_DEVICE_RESULT.SUCCESS { | |
LogService.sharedService.debug(data: "Find Devices Failed - NON DEVICE") | |
completion(result, nil) | |
} | |
else { | |
var logStr = "" | |
for device in devices! { | |
logStr += "id=\(device.deviceId!);" | |
} | |
LogService.sharedService.log(event: .DEVICES_RECEIVED, data: logStr) | |
completion(FIND_DEVICE_RESULT.SUCCESS, devices) | |
} | |
}) | |
} | |
}) | |
} | |
private var maxRetryCount = 6 | |
private func findNearByDevices(completion:@escaping FindDeviceCompletionHandler) { | |
self.findDeviceTimer = Timer.scheduledTimer(withTimeInterval: Constants.FIND_DEVICE_TIME_INTERVAL, repeats: true, block: { | |
t in | |
self.getDevicesInRange(completion: { | |
result, devices in | |
if result != FIND_DEVICE_RESULT.SUCCESS { | |
if self.maxRetryCount == 0 { | |
self.maxRetryCount = 6 | |
self.findDeviceTimer?.invalidate() | |
self.findDeviceTimer = nil | |
completion(result, nil) | |
return | |
} | |
else { | |
self.maxRetryCount -= 1 | |
LogService.sharedService.debug(data: "Left Find Devices Retry Count - \(self.maxRetryCount)") | |
return | |
} | |
} | |
self.findDeviceTimer?.invalidate() | |
self.findDeviceTimer = nil | |
self.model?.setDevices(devices: devices!) | |
completion(FIND_DEVICE_RESULT.SUCCESS, devices) | |
}) | |
}) | |
} | |
private func getDevicesInRange(completion: @escaping FindDeviceCompletionHandler) { | |
let appID:String = CirrentService.sharedService.setAppIdentifier()! | |
APIService.sharedService.getDevicesInRange(appID: appID, completion: { | |
data, response, error in | |
guard let _ = data, error == nil else { | |
LogService.sharedService.debug(data: "Get Devices In Range Failed - NO_RESPONSE") | |
completion(FIND_DEVICE_RESULT.FAILED_NO_RESPONSE, nil) | |
return | |
} | |
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { | |
LogService.sharedService.debug(data: "Get Devices In Range Failed - INVALID_STATUS:\(httpStatus.statusCode)") | |
completion(FIND_DEVICE_RESULT.FAILED_INVALID_STATUS, nil) | |
return | |
} | |
let str = String(data: data!, encoding: .utf8) | |
print(str!) | |
let jsonData:JSON = JSON(data: data!) | |
let jsonArray = jsonData["devices"] | |
var deviceArray:[Device] = [Device]() | |
for item in jsonArray { | |
let device = self.getDeviceFromJson(data: item.1) | |
deviceArray.append(device) | |
} | |
if deviceArray.count == 0 { | |
LogService.sharedService.debug(data: "Get Devices In Range Failed - NO_DEVICES") | |
completion(FIND_DEVICE_RESULT.FAILED_NO_DEVICE, nil) | |
} | |
else { | |
LogService.sharedService.debug(data: "Get Devices In Range Success") | |
completion(FIND_DEVICE_RESULT.SUCCESS, deviceArray) | |
} | |
}) | |
} | |
public func identifyYourself(deviceID:String, completion:@escaping CompletionHandler) { | |
APIService.sharedService.identifyYourself(deviceID: deviceID, completion: { | |
data, response, error in | |
guard let _ = data, error == nil else { | |
LogService.sharedService.debug(data: "\(deviceID) - Identify Yourself Failed " + LogService.getResponseErrorString(response: .FAILED_NO_RESPONSE)) | |
completion(.FAILED_NO_RESPONSE) | |
return | |
} | |
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { | |
LogService.sharedService.debug(data: "\(deviceID) - Identify Yourself Failed " + LogService.getResponseErrorString(response: .FAILED_INVALID_STATUS)) | |
completion(.FAILED_INVALID_STATUS) | |
return | |
} | |
LogService.sharedService.debug(data: "\(deviceID) - Identify Yourself Success") | |
completion(.SUCCESS) | |
}) | |
} | |
private var userActionTimer:Timer! | |
public func pollForUserAction(completion:@escaping UserActionCompletionHandler) { | |
if model == nil || model!.devices == nil || model!.devices!.count == 0 { | |
return | |
} | |
userActionTimer = Timer.scheduledTimer(withTimeInterval: Constants.USER_ACTION_TIME_INTERVAL, repeats: true, block: { | |
t in | |
for dev in self.model!.devices! { | |
if dev.userActionEnabled == false { | |
continue | |
} | |
self.getDeviceStatus(device: dev, completion: { | |
response, status in | |
if response == .SUCCESS && status != nil { | |
if status!["user_action"] != nil && status!["user_action"] != "" | |
{ | |
dev.confirmedOwnerShip = true | |
completion(dev, status!["user_action"].stringValue) | |
} | |
} | |
}) | |
} | |
}) | |
} | |
public func stopPollForUserAction() { | |
if userActionTimer != nil { | |
userActionTimer.invalidate() | |
} | |
} | |
private func getDeviceStatus(device:Device, completion:@escaping DeviceStatusCompletionHandler) { | |
APIService.sharedService.getDeviceStatus(deviceID: device.deviceId, completion: { | |
data, response, error in | |
guard let _ = data, error == nil else { | |
LogService.sharedService.log(event: .STATUS_ERROR, data: "Error=" + LogService.getResponseErrorString(response: .FAILED_NO_RESPONSE)) | |
LogService.sharedService.putLog() | |
completion(.FAILED_NO_RESPONSE, nil) | |
return | |
} | |
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { | |
LogService.sharedService.log(event: .STATUS_ERROR, data: "Error=" + LogService.getResponseErrorString(response: .FAILED_INVALID_STATUS)) | |
LogService.sharedService.putLog() | |
completion(.FAILED_INVALID_STATUS, nil) | |
return | |
} | |
let status:JSON = JSON(data: data!) | |
let jsonStr = LogService.jsonStringfy(json: status) | |
if jsonStr != nil { | |
LogService.sharedService.log(event: .STATUS, data: "json=" + jsonStr!) | |
LogService.sharedService.putLog() | |
} | |
completion(.SUCCESS, status) | |
}) | |
} | |
public func getDeviceIndex(device:Device) -> Int { | |
if model == nil || model!.devices == nil || model!.devices!.count == 0 { | |
return -1 | |
} | |
var index:Int = 0 | |
for dev in model!.devices! { | |
if dev.deviceId == device.deviceId { | |
return index | |
} | |
index += 1 | |
} | |
return -1 | |
} | |
public func putProviderCredentials(providerUDID: String, completion: @escaping CredentialCompletionHadler) { | |
let appID:String = CirrentService.sharedService.setAppIdentifier()! | |
let deviceID:String = model!.selectedDevice!.deviceId | |
APIService.sharedService.putProviderCredentials(appID: appID, deviceID: deviceID, providerID: providerUDID, completion: { | |
data, response, error in | |
guard let _ = data, error == nil else { | |
LogService.sharedService.debug(data: "Put Provider Network Failed - NO_RESPONSE") | |
completion(CREDENTIAL_RESPONSE.FAILED_NO_RESPONSE, nil) | |
return | |
} | |
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { | |
LogService.sharedService.debug(data: "Put Provider Network Failed - INVALID_STATUS:\(httpStatus.statusCode)") | |
completion(CREDENTIAL_RESPONSE.FAILED_INVALID_STATUS, nil) | |
return | |
} | |
let responseString = String(data: data!, encoding: .utf8)! | |
let credentials:[String] = self.getCredentialsFromString(str: responseString) | |
LogService.sharedService.debug(data:"Put Provider Network Credentials=\(responseString)") | |
completion(CREDENTIAL_RESPONSE.SUCCESS, credentials) | |
}) | |
} | |
public func selectDeviceAndAskStatus(device:Device, completion:@escaping CompletionHandler) { | |
model!.selectedDevice = device | |
let deviceID:String = device.deviceId! | |
let logStr = "id=\(deviceID)" | |
LogService.sharedService.log(event: .DEVICE_SELECTED, data: logStr) | |
APIService.sharedService.getDeviceStatus(deviceID: device.deviceId, completion: { | |
data, response, error in | |
guard let _ = data, error == nil else { | |
LogService.sharedService.debug(data: "Get Device Status Failed - NO_RESPONSE") | |
completion(.FAILED_NO_RESPONSE) | |
return | |
} | |
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { | |
LogService.sharedService.debug(data: "Get Device Status Failed - INVALID_STATUS:\(httpStatus.statusCode)") | |
completion(.FAILED_INVALID_STATUS) | |
return | |
} | |
let status:JSON = JSON(data: data!) | |
let logString:String? = LogService.jsonStringfy(json: status) | |
if logString != nil { | |
LogService.sharedService.log(event: .STATUS, data: "json=" + logString!) | |
} | |
self.model?.GCN = true | |
if status["wifi_scans"] != nil && status["wifi_scans"].count > 0 { | |
self.model?.setNetworks(data: status["wifi_scans"]) | |
} | |
else { | |
self.model?.setNetworks(data: []) | |
} | |
if status["known_networks"] != nil && status["known_networks"].count > 0 { | |
let dataArray:[AnyObject] = status["known_networks"].arrayObject as! [AnyObject] | |
for net in dataArray { | |
let netData:JSON = JSON(net) | |
if netData["status"] != nil && String(describing: netData["status"]) == "JOINED" { | |
//if netData["ssid"] != nil && String(describing: netData["ssid"]) == Constants.XFINITY_SSID { | |
// self.model?.zipkeyhotspot = Constants.XFINITY_ZIPKEY_HOTSPOT | |
//} | |
break | |
} | |
} | |
} | |
if (device.provider_known_network != nil && device.provider_known_network.count > 0) { | |
self.model?.providerNetworkList = [ProviderKnownNetwork]() | |
for network in device.provider_known_network { | |
let net:ProviderKnownNetwork = ProviderKnownNetwork() | |
net.ssid = network.ssid | |
net.providerLogo = network.providerLogo | |
net.providerName = network.providerName | |
net.providerUUID = network.providerUUID | |
net.providerLearnMoreURL = network.providerLearnMoreURL | |
self.model?.providerNetworkList!.append(net) | |
} | |
} | |
completion(.SUCCESS) | |
}) | |
} | |
private func getCredentialsFromString(str: String) -> [String] { | |
var credString:String = str | |
credString.remove(at: credString.startIndex) | |
credString.remove(at: credString.index(before: credString.endIndex)) | |
credString = credString.trimmingCharacters(in: .whitespaces) | |
let creds = credString.characters.split{ | |
$0 == "," | |
}.map(String.init) | |
var credentials:[String] = [String]() | |
for cred in creds { | |
var newCred:String = String(cred) | |
newCred.remove(at: newCred.startIndex) | |
newCred.remove(at: newCred.index(before: newCred.endIndex)) | |
credentials.append(newCred) | |
} | |
return credentials | |
} | |
public func putPrivateCredentials(completion: @escaping CredentialCompletionHadler) { | |
if (model?.GCN)! { | |
model?.credentialId = nil | |
APIService.sharedService.deviceJoinNetwork(deviceID: (model?.selectedDevice?.deviceId)!, network: (model?.selectedNetwork!)!, password: (model?.selectedNetworkPassword)!, completion: { | |
data, response, error in | |
guard let _ = data, error == nil else { | |
LogService.sharedService.debug(data: "Device Join Network Failed - NO_RESPONSE") | |
completion(.FAILED_NO_RESPONSE, nil) | |
return | |
} | |
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { | |
LogService.sharedService.debug(data: "Device Join Network Failed - INVALID_STATUS") | |
completion(.FAILED_INVALID_STATUS, nil) | |
return | |
} | |
let responseString = String(data: data!, encoding: .utf8)! | |
var credentials:[String] = self.getCredentialsFromString(str: responseString) | |
self.model?.credentialId = credentials[0] | |
LogService.sharedService.debug(data: "Device Join Network Success - \(responseString)") | |
completion(.SUCCESS, credentials) | |
}) | |
} | |
else { | |
guard let ssid = getCurrentSSID() else { | |
LogService.sharedService.debug(data: "Send Credential Failed on SoftAp - SSID = Nil") | |
completion(CREDENTIAL_RESPONSE.FAILED_NO_RESPONSE, nil) | |
return | |
} | |
if ssid.contains(softApSSID) != true { | |
LogService.sharedService.debug(data: "Send Credential Failed on SoftAp - NOT_SOFTAP_NETWORK") | |
completion(CREDENTIAL_RESPONSE.NOT_SOFTAP, nil) | |
return | |
} | |
let enteredPassword = model?.selectedNetworkPassword | |
var password = "" | |
if model?.scdKey != nil { | |
let orgKeyData:String = (model?.scdKey!)! | |
let prefix = "-----BEGIN PUBLIC KEY-----\n" | |
let surfix = "\n-----END PUBLIC KEY-----\n" | |
let startIndex = orgKeyData.index(orgKeyData.startIndex, offsetBy: prefix.characters.count) | |
let endIndex = orgKeyData.index(orgKeyData.endIndex, offsetBy: -(surfix.characters.count)) | |
let range = startIndex..<endIndex | |
var key = orgKeyData.substring(with: range) | |
key = key.replacingOccurrences(of: "\n", with: "", options: .regularExpression) | |
let data = RSAUtils.encryptWithRSAPublicKey(enteredPassword!.data(using: .utf8)!, pubkeyBase64: key, keychainTag: "Cirrent") | |
password = data!.base64EncodedString() | |
} | |
APIService.sharedService.putSoftApJoinNetwork(softApIp: (model?.softApIp!)!, network: (model?.selectedNetwork!)!, password: (model?.selectedNetworkPassword!)!, encryptedPassword: password, completion: { | |
data, response, error in | |
guard let _ = data, error == nil else { | |
LogService.sharedService.debug(data: "Put SoftAp Join Network Failed - NO_RESPONSE") | |
completion(.FAILED_NO_RESPONSE, nil) | |
return | |
} | |
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { | |
LogService.sharedService.debug(data: "Put SoftAp Join Network Failed - INVALID_STATUS:\(httpStatus.statusCode)") | |
completion(.FAILED_INVALID_STATUS, nil) | |
return | |
} | |
let responseString = String(data: data!, encoding: .utf8)! | |
let credentials:[String] = self.getCredentialsFromString(str: responseString) | |
completion(.SUCCESS, credentials) | |
}) | |
} | |
} | |
private var joiningTimer:Timer! | |
private func stopGetDeviceJoiningStatus() { | |
if joiningTimer != nil { | |
joiningTimer.invalidate() | |
} | |
} | |
public func getDeviceJoiningStatus(handler:@escaping JoiningHandler) { | |
var override = false | |
var index = 1 | |
var joiningIndex = 1 | |
var waitTime = 12 | |
joiningTimer = Timer.scheduledTimer(withTimeInterval: Constants.JOINING_TIME_INTERVAL, repeats: true, block: { | |
t in | |
if self.model?.GCN == true || override == true { | |
if self.model?.selectedDevice == nil { | |
LogService.sharedService.debug(data: "JOINING - Selected Device is Nil") | |
handler(JOINING_STATUS.SELECTED_DEVICE_NIL) | |
t.invalidate() | |
return | |
} | |
self.getDeviceStatus(device: (self.model?.selectedDevice!)!, completion: { | |
response, status in | |
if response == RESPONSE.FAILED_NO_RESPONSE { | |
LogService.sharedService.debug(data: "JOINING - Get Device Status Failed - NO_RESPONSE") | |
handler(JOINING_STATUS.FAILED_NO_RESPONSE) | |
} | |
else if response == RESPONSE.FAILED_INVALID_STATUS { | |
LogService.sharedService.debug(data: "JOINING - Get Device Status Failed - INVALID_STATUS") | |
handler(JOINING_STATUS.FAILED_INVALID_STATUS) | |
} | |
else { | |
index += 1 | |
if index > waitTime { | |
t.invalidate() | |
if override { | |
override = false | |
LogService.sharedService.debug(data: "JOINING - Failed - TIMED OUT TRIED API") | |
handler(JOINING_STATUS.TIMED_OUT_TRIED_API) | |
return | |
} | |
else { | |
LogService.sharedService.debug(data: "JOINING - Failed - TIMED OUT") | |
handler(JOINING_STATUS.TIMED_OUT) | |
return | |
} | |
} | |
if status == nil { | |
t.invalidate() | |
LogService.sharedService.debug(data: "JOINING - Failed - GET DEVICE STATUS FAILED") | |
handler(JOINING_STATUS.GET_DEVICE_STATUS_FAILED) | |
return | |
} | |
LogService.sharedService.debug(data: "Credential - " + (self.model?.credentialId!)!) | |
if status!["known_networks"] != nil && status!["known_networks"].count > 0 { | |
let dataArray:[AnyObject] = status!["known_networks"].arrayObject as! [AnyObject] | |
for net in dataArray { | |
let network:JSON = JSON(net) | |
if String(describing: network["ssid"]) == (self.model?.selectedNetwork!.ssid)! && String(describing: network["status"]) == "JOINED" && (override == true || (override != true && String(describing: network["credential_id"]) == (self.model?.credentialId!)!)) { | |
t.invalidate() | |
LogService.sharedService.debug(data: "JOINING - Success") | |
handler(JOINING_STATUS.JOINED) | |
return | |
} | |
else if String(describing: network["ssid"]) == (self.model?.selectedNetwork!.ssid)! && String(describing: network["status"]) == "JOINING" && String(describing: network["credential_id"]) == (self.model?.credentialId!)! { | |
if joiningIndex == 1 { | |
LogService.sharedService.debug(data: "JOINING - Received Creds") | |
handler(JOINING_STATUS.RECEIVED_CREDS) | |
waitTime = 34 | |
} | |
if joiningIndex == 2 { | |
LogService.sharedService.debug(data: "JOINING - Attempting To Join") | |
handler(JOINING_STATUS.ATTEMPTING_TO_JOIN) | |
} | |
if joiningIndex == 3 { | |
LogService.sharedService.debug(data: "JOINING - Optimizing Connetion") | |
handler(JOINING_STATUS.OPTIMIZING_CONNECTION) | |
} | |
joiningIndex += 1 | |
} | |
else if String(describing: network["ssid"]) == (self.model?.selectedNetwork!.ssid)! && (String(describing: network["status"]) == "DISCONNECTED" || String(describing: network["status"]) == "FAILED") && (override == true || (override == false && String(describing: network["credential_id"]) == (self.model?.credentialId!)!)) { | |
t.invalidate() | |
LogService.sharedService.debug(data: "JOINING - Failed - DISCONNECTED") | |
handler(JOINING_STATUS.FAILED) | |
return | |
} | |
} | |
} | |
} | |
}) | |
} | |
else { | |
let ssid:String? = self.getCurrentSSID() | |
if ssid != nil && ssid!.contains(self.softApSSID) != true { | |
override = true | |
LogService.sharedService.debug(data: "JOINING SOFTAP - Failed - NOT_SOFTAP_NETWORK") | |
handler(JOINING_STATUS.NOT_SOFTAP_NETWORK) | |
return | |
} | |
APIService.sharedService.getSoftApDeviceStatus(softApIp: (self.model?.softApIp!)!, completion: { | |
data, response, error in | |
guard let _ = data, error == nil else { | |
LogService.sharedService.debug(data: "JOINING SOFTAP - Failed - NO_RESPONSE") | |
handler(JOINING_STATUS.FAILED_NO_RESPONSE) | |
return | |
} | |
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { | |
LogService.sharedService.debug(data: "JOINING SOFTAP - Failed - INVALID_STATUS") | |
handler(JOINING_STATUS.FAILED_INVALID_STATUS) | |
return | |
} | |
index += 1 | |
if index > 12 { | |
t.invalidate() | |
LogService.sharedService.debug(data: "JOINING SOFTAP - Failed - TIMED_OUT") | |
handler(JOINING_STATUS.TIMED_OUT) | |
return | |
} | |
let status:JSON = JSON(data: data!) | |
if status == nil { | |
t.invalidate() | |
LogService.sharedService.debug(data: "JOINING SOFTAP - Failed - GET_DEVICE_STATUS_FAILED") | |
handler(JOINING_STATUS.GET_DEVICE_STATUS_FAILED) | |
} | |
if status["known_networks"] != nil && status["known_networks"].count > 0 { | |
let dataArray:[AnyObject] = status["known_networks"].arrayObject as! [AnyObject] | |
for net in dataArray { | |
let network:JSON = JSON(net) | |
if String(describing: network["ssid"]) == (self.model?.selectedNetwork?.ssid)! && String(describing: network["status"]) == "JOINED" { | |
t.invalidate() | |
LogService.sharedService.debug(data: "JOINING SOFTAP - Success") | |
handler(JOINING_STATUS.JOINED) | |
return | |
} | |
else if String(describing: network["ssid"]) == (self.model?.selectedNetwork?.ssid)! && String(describing: network["status"]) == "FAILED" { | |
t.invalidate() | |
LogService.sharedService.debug(data: "JOINING SOFTAP - Failed") | |
handler(JOINING_STATUS.FAILED) | |
return | |
} | |
} | |
} | |
}) | |
} | |
}) | |
} | |
public func stopAllAction() { | |
if findDeviceTimer != nil { | |
findDeviceTimer?.invalidate() | |
} | |
if joiningTimer != nil { | |
joiningTimer.invalidate() | |
} | |
if userActionTimer != nil { | |
userActionTimer.invalidate() | |
} | |
findDeviceTimer = nil | |
joiningTimer = nil | |
userActionTimer = nil | |
} | |
public func checkSoftApAndRun() -> Bool { | |
let ssid:String? = CirrentService.sharedService.getCurrentSSID() | |
if ssid == nil { | |
return false | |
} | |
if ssid!.contains(CirrentService.sharedService.softApSSID) == true { | |
let softApNotify = Notification.Name(Constants.SOFTAP_NOTIFICATION_NAME) | |
NotificationCenter.default.post(name: softApNotify, object: nil) | |
LogService.sharedService.putLog() | |
return true | |
} | |
else { | |
return false | |
} | |
} | |
private var softApTimer:Timer! | |
private var maxSoftApRetryCount = 3 | |
public func processSoftAp(handler: @escaping SoftApHandler) { | |
initModel() | |
if model != nil && model?.ssid != nil && model?.ssid!.contains(softApSSID) == true { | |
let ipAddress = getWiFiAddress() | |
if ipAddress == nil { | |
LogService.sharedService.debug(data: "SOFTAP - Failed - SoftAp IP address is Nil") | |
handler(.FAILED_NOT_GET_SOFTAP_IP) | |
return | |
} | |
model?.setSoftApIp(ip: ipAddress!) | |
LogService.sharedService.debug(data: "SoftAp Ip address - \((model?.softApIp!)!)") | |
softApTimer = Timer.scheduledTimer(withTimeInterval: Constants.SOFTAP_TIME_INTERVAL, repeats: true, block: { | |
t in | |
APIService.sharedService.getSoftApDeviceInfo(softApIp: (self.model?.softApIp!)!, completion: { | |
data, response, error in | |
guard let _ = data, error == nil else { | |
self.maxSoftApRetryCount -= 1 | |
if self.maxSoftApRetryCount == 0 { | |
self.softApTimer.invalidate() | |
LogService.sharedService.debug(data: "SOFTAP - Failed - GET_SOFTAP_DEVICE_INFO_NO_RESPONSE") | |
handler(.FAILED_SOFTAP_NO_RESPONSE) | |
} | |
return | |
} | |
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { | |
self.maxSoftApRetryCount -= 1 | |
if self.maxSoftApRetryCount == 0 { | |
self.softApTimer.invalidate() | |
LogService.sharedService.debug(data: "SOFTAP - Failed - GET_SOFTAP_DEVICE_INFO_INVALID_STATUS") | |
handler(.FAILED_SOFTAP_INVALID_STATUS) | |
} | |
return | |
} | |
let info = JSON(data: data!) | |
if info != nil && info["scd_public_key"] != nil { | |
self.model?.scdKey = info["scd_public_key"].stringValue | |
} | |
let device = Device() | |
device.macAddress = info["device_id"].stringValue | |
device.deviceId = info["device_id"].stringValue | |
self.model?.devices = [] | |
self.model?.devices?.append(device) | |
let selectedDevice = self.model?.getFirstDevice() | |
if selectedDevice != nil { | |
self.model?.selectedDevice = selectedDevice! | |
} | |
APIService.sharedService.getSoftApDeviceStatus(softApIp: (self.model?.softApIp!)!, completion: { | |
data, response, error in | |
guard let _ = data, error == nil else { | |
self.maxSoftApRetryCount -= 1 | |
if self.maxSoftApRetryCount == 0 { | |
self.softApTimer.invalidate() | |
LogService.sharedService.debug(data: "SOFTAP - Failed - GET_SOFTAP_DEVICE_STATUS_NO_RESPONSE") | |
handler(.FAILED_SOFTAP_NO_RESPONSE) | |
} | |
return | |
} | |
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { | |
self.maxSoftApRetryCount -= 1 | |
if self.maxSoftApRetryCount == 0 { | |
self.softApTimer.invalidate() | |
LogService.sharedService.debug(data: "SOFTAP - Failed - GET_SOFTAP_DEVICE_STATUS_INVALID_STATUS") | |
handler(.FAILED_SOFTAP_INVALID_STATUS) | |
} | |
return | |
} | |
let status = JSON(data: data!) | |
let known_networks:JSON? = status["known_networks"] | |
var bShouldStopSoftAp:Bool = false | |
if known_networks != nil { | |
let network:[AnyObject] = known_networks!.arrayObject as! [AnyObject] | |
for net in network { | |
let netData:JSON? = JSON(net) | |
if netData == nil { | |
continue | |
} | |
if netData != nil && netData?["status"] != nil { | |
let status:String = String(describing: netData!["status"]) | |
if status == "JOINED" { | |
bShouldStopSoftAp = true | |
break | |
} | |
} | |
} | |
} | |
if bShouldStopSoftAp == true { | |
self.softApTimer.invalidate() | |
APIService.sharedService.stopSoftAp(softApIp: (self.model?.softApIp!)!, completion: { | |
data, response, error in | |
guard let _ = data, error == nil else { | |
LogService.sharedService.debug(data: "SOFTAP - Failed - MEET_ME_IN_CLOUD_FAILED") | |
//handler(.FAILED_MEET_ME_IN_CLOUD) | |
self.successSoftAp(info: info, wifiScans: status["wifi_scans"], handler: handler) | |
return | |
} | |
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { | |
LogService.sharedService.debug(data: "SOFTAP - Failed - MEET_ME_IN_CLOUD_FAILED") | |
//handler(.FAILED_MEET_ME_IN_CLOUD) | |
self.successSoftAp(info: info, wifiScans: status["wifi_scans"], handler: handler) | |
return | |
} | |
self.selectDeviceAndAskStatus(device: (self.model?.selectedDevice!)!, completion: { | |
response in | |
if response == RESPONSE.SUCCESS { | |
LogService.sharedService.debug(data: "SOFTAP - Success - SUCCESS_TO_MEET_ME_IN_CLOUD") | |
handler(.SUCCESS_MEET_ME_IN_CLOUD) | |
return | |
} | |
else { | |
LogService.sharedService.debug(data: "SOFTAP - Failed - MEET_ME_IN_CLOUD_FAILED") | |
//handler(.FAILED_MEET_ME_IN_CLOUD) | |
self.successSoftAp(info: info, wifiScans: status["wifi_scans"], handler: handler) | |
return | |
} | |
}) | |
}) | |
} | |
else { | |
self.successSoftAp(info: info, wifiScans: status["wifi_scans"], handler: handler) | |
return | |
} | |
}) | |
}) | |
}) | |
} | |
else { | |
LogService.sharedService.debug(data: "SOFTAP - Failed - NOT_SOFTAP_SSID") | |
handler(.FAILED_NOT_SOFTAP_SSID) | |
return | |
} | |
} | |
private func successSoftAp(info:JSON, wifiScans:JSON, handler: @escaping SoftApHandler) { | |
self.model?.GCN = false | |
self.model?.setSoftApNetworks(data: wifiScans) | |
let device = Device() | |
device.macAddress = info["device_id"].stringValue | |
device.deviceId = info["device_id"].stringValue | |
self.model?.devices = [] | |
self.model?.devices?.append(device) | |
let selectedDevice = self.model?.getFirstDevice() | |
self.model?.selectedDevice = selectedDevice | |
self.softApTimer.invalidate() | |
LogService.sharedService.debug(data: "SOFTAP - Success - SUCCESS_WITH_SOFTAP") | |
handler(.SUCCESS_WITH_SOFTAP) | |
} | |
// Private Methods | |
private func initModel() { | |
model = Model() | |
model?.ssid = getCurrentSSID() | |
model?.bssid = getCurrentBSSID() | |
} | |
private var environmentTimer:Timer! | |
private var uploadingEnvironmentNow:Bool = false | |
private func uploadEnvironment(completion: @escaping CompletionHandler) { | |
let appID:String = setAppIdentifier()! | |
initModel() | |
APIService.sharedService.startLocationManager() | |
let afterTime = DispatchTime.now() + Constants.UPLOAD_ENVIRONMENT_TIME_INTERVAL | |
DispatchQueue.main.asyncAfter(deadline: afterTime, execute: { | |
self.environmentTimer = Timer.scheduledTimer(withTimeInterval: Constants.UPLOAD_ENVIRONMENT_TIME_INTERVAL, repeats: true, block: { | |
timer in | |
if self.uploadingEnvironmentNow == false { | |
self.uploadingEnvironmentNow = true | |
APIService.sharedService.uploadEnvironment(appID: appID, model: self.model!, callback: { | |
response, accuracy in | |
self.uploadingEnvironmentNow = false | |
if response == .FAILED_NO_RESPONSE { | |
if accuracy > 200 { | |
LogService.sharedService.debug(data: "Upload Environment Failed - INACCURATE LOCATION (Trying Again)") | |
} | |
else { | |
LogService.sharedService.debug(data: "Upload Environment Failed - NO_RESPONSE") | |
completion(.FAILED_NO_RESPONSE) | |
APIService.sharedService.stopLocationManager() | |
self.environmentTimer.invalidate() | |
} | |
} | |
else if response == .FAILED_INVALID_STATUS { | |
LogService.sharedService.debug(data: "Upload Environment Failed - INVALID_STATUS:\(Int(accuracy))") | |
completion(.FAILED_INVALID_STATUS) | |
APIService.sharedService.stopLocationManager() | |
self.environmentTimer.invalidate() | |
} | |
else { | |
LogService.sharedService.debug(data: "Upload Environment Success") | |
completion(.SUCCESS) | |
APIService.sharedService.stopLocationManager() | |
self.environmentTimer.invalidate() | |
} | |
}) | |
} | |
}) | |
}) | |
} | |
private func getDeviceFromJson(data:JSON) -> Device { | |
let device:Device = Device() | |
device.idDeviceId = data["idDeviceId"] != nil ? data["idDeviceId"].intValue : -1 | |
device.idDeviceType = data["idDeviceType"] != nil ? data["idDeviceType"].intValue : -1 | |
device.deviceId = data["deviceId"] != nil ? data["deviceId"].stringValue : "" | |
device.macAddress = data["MACAddr"] != nil ? data["MACAddr"].stringValue : "" | |
device.imageURL = data["imageURL"] != nil ? data["imageURL"].stringValue : "" | |
device.uptime = data["uptime"] != nil ? data["uptime"].doubleValue : -1 | |
device.identifyingActionEnabled = data["identifying_action_enabled"] != nil ? data["identifying_action_enabled"].boolValue : false | |
device.identifyingActionDescription = data["identifying_action_description"] != nil ? data["identifying_action_description"].stringValue : "" | |
device.userActionEnabled = data["user_action_enabled"] != nil ? data["user_action_enabled"].boolValue : false | |
device.userActionDescription = data["user_action_description"] != nil ? data["user_action_description"].stringValue : "" | |
if data["provider_known_network"] == nil { | |
return device | |
} | |
device.provider_known_network = [ProviderKnownNetwork]() | |
let dataArray:[AnyObject] = data["provider_known_network"].arrayObject as! [AnyObject] | |
for netData in dataArray { | |
let net:JSON = JSON(netData) | |
let provider_net = ProviderKnownNetwork() | |
provider_net.ssid = net["ssid"] != nil ? net["ssid"].stringValue : "" | |
provider_net.providerName = net["provider_name"] != nil ? net["provider_name"].stringValue : "" | |
provider_net.providerUUID = net["provider_uuid"] != nil ? net["provider_uuid"].stringValue : "" | |
provider_net.providerLogo = net["provider_logo"] != nil ? net["provider_logo"].stringValue : "" | |
provider_net.providerLearnMoreURL = net["provider_learn_more"] != nil ? net["provider_learn_more"].stringValue : "" | |
provider_net.providerAttribution = net["provider_attribution"] != nil ? net["provider_attribution"].stringValue : "" | |
provider_net.providerAttributionLogo = net["provider_attribution_logo"] != nil ? net["provider_attribution_logo"].stringValue : "" | |
print (provider_net.providerLearnMoreURL) | |
device.provider_known_network.append(provider_net) | |
} | |
return device | |
} | |
private func generateUUID() -> String { | |
let pattern = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx" | |
var secs = UInt32(Date().timeIntervalSince1970) | |
var uuid:String = String() | |
for char in pattern.characters { | |
let r = ((secs + arc4random() * 16) % 16) | 0 | |
secs = UInt32(floor(Double(secs) / 16)) | |
if char == "x" { | |
uuid += String(format: "%X", r) | |
} | |
else if char == "y" { | |
let val = r & 0x3 | 0x8 | |
uuid += String(format: "%X", val) | |
} | |
else { | |
uuid += String(char) | |
} | |
} | |
return uuid | |
} | |
private var reachability:Reachability? = nil | |
private var networkStatus:Int = 0 | |
//0 : Not Reachable | |
//1 : Reachable via Wifi | |
//2 : Reachable via Cellular | |
func initReachability() { | |
if reachability == nil { | |
reachability = Reachability()! | |
} | |
else { | |
return | |
} | |
reachability!.whenReachable = { reachability in | |
DispatchQueue.main.async { | |
if self.reachability!.isReachableViaWiFi { | |
LogService.sharedService.debug(data: "Reachable via Wifi.") | |
self.networkStatus = 1 | |
} else { | |
LogService.sharedService.debug(data: "Reachable via Cellular.") | |
self.networkStatus = 2 | |
} | |
} | |
} | |
reachability!.whenUnreachable = { reachability in | |
DispatchQueue.main.async { | |
LogService.sharedService.debug(data: "Not Reachable") | |
self.networkStatus = 0 | |
} | |
} | |
do { | |
try reachability!.startNotifier() | |
} catch { | |
reachability = nil | |
} | |
} | |
public func isOnCellularNetwork() -> Bool { | |
if networkStatus == 2 { | |
LogService.sharedService.debug(data: "Phone is on Cellular Network.") | |
return true | |
} | |
else { | |
LogService.sharedService.debug(data: "Phone is not on Cellular Network.") | |
return false | |
} | |
} | |
public func getCurrentSSID() -> String? { | |
initReachability() | |
guard let unwrappedCFArrayInterfaces = CNCopySupportedInterfaces() else { | |
LogService.sharedService.debug(data: "this must be a simulator, no interfaces found") | |
return nil | |
} | |
guard let swiftInterfaces = (unwrappedCFArrayInterfaces as NSArray) as? [String] else { | |
LogService.sharedService.debug(data: "System error: did not come back as array of Strings") | |
return nil | |
} | |
for interface in swiftInterfaces { | |
LogService.sharedService.debug(data: "Looking up SSID info for \(interface)") // en0 | |
guard let unwrappedCFDictionaryForInterface = CNCopyCurrentNetworkInfo(interface as CFString) else { | |
LogService.sharedService.debug(data: "System error: \(interface) has no information") | |
return nil | |
} | |
guard let SSIDDict = (unwrappedCFDictionaryForInterface as NSDictionary) as? [String: AnyObject] else { | |
LogService.sharedService.debug(data: "System error: interface information is not a string-keyed dictionary") | |
return nil | |
} | |
for d in SSIDDict.keys { | |
LogService.sharedService.debug(data: "\(d)=\(SSIDDict[d]!)") | |
} | |
return SSIDDict["SSID"] as! String? | |
} | |
return nil | |
} | |
private func getCurrentBSSID() -> String? { | |
guard let unwrappedCFArrayInterfaces = CNCopySupportedInterfaces() else { | |
LogService.sharedService.debug(data: "this must be a simulator, no interfaces found") | |
return nil | |
} | |
guard let swiftInterfaces = (unwrappedCFArrayInterfaces as NSArray) as? [String] else { | |
LogService.sharedService.debug(data: "System error: did not come back as array of Strings") | |
return nil | |
} | |
for interface in swiftInterfaces { | |
LogService.sharedService.debug(data: "Looking up SSID info for \(interface)") // en0 | |
guard let unwrappedCFDictionaryForInterface = CNCopyCurrentNetworkInfo(interface as CFString) else { | |
LogService.sharedService.debug(data: "System error: \(interface) has no information") | |
return nil | |
} | |
guard let SSIDDict = (unwrappedCFDictionaryForInterface as NSDictionary) as? [String: AnyObject] else { | |
LogService.sharedService.debug(data: "System error: interface information is not a string-keyed dictionary") | |
return nil | |
} | |
for d in SSIDDict.keys { | |
LogService.sharedService.debug(data: "\(d)=\(SSIDDict[d]!)") | |
} | |
return SSIDDict["BSSID"] as! String? | |
} | |
return nil | |
} | |
private func getWiFiAddress() -> String? { | |
var address : String? | |
// Get list of all interfaces on the local machine: | |
var ifaddr : UnsafeMutablePointer<ifaddrs>? | |
guard getifaddrs(&ifaddr) == 0 else { | |
LogService.sharedService.debug(data: "Get IP Address Failed") | |
return nil | |
} | |
guard let firstAddr = ifaddr else { | |
LogService.sharedService.debug(data: "Get IP Address Failed") | |
return nil | |
} | |
// For each interface ... | |
for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) { | |
let interface = ifptr.pointee | |
// Check for IPv4 or IPv6 interface: | |
let addrFamily = interface.ifa_addr.pointee.sa_family | |
if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) { | |
// Check interface name: | |
let name = String(cString: interface.ifa_name) | |
if name == "en0" { | |
// Convert interface address to a human readable string: | |
var addr = interface.ifa_addr.pointee | |
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST)) | |
getnameinfo(&addr, socklen_t(interface.ifa_addr.pointee.sa_len), | |
&hostname, socklen_t(hostname.count), | |
nil, socklen_t(0), NI_NUMERICHOST) | |
address = String(cString: hostname) | |
} | |
} | |
} | |
freeifaddrs(ifaddr) | |
LogService.sharedService.debug(data: "IP Address:" + address!) | |
return address | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment