Skip to content

Instantly share code, notes, and snippets.

@macropok
Created January 20, 2017 14:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save macropok/3df8ba519163d6e66d1de3b9819d49bd to your computer and use it in GitHub Desktop.
Save macropok/3df8ba519163d6e66d1de3b9819d49bd to your computer and use it in GitHub Desktop.
//
// 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