Created
April 28, 2018 12:41
-
-
Save castus/fea6d241f967d8cc63aeb009142f1c65 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
import Foundation | |
import AWSIoT | |
import SwiftyJSON | |
class LiveSynchronizationController { | |
private var connected = false | |
private var iotDataManager: AWSIoTDataManager! | |
private var iotManager: AWSIoTManager! | |
private var iot: AWSIoT! | |
private var topic = "" | |
private var certificateIdUserDefaultsKey = "certificateId" | |
private var certificateArnUserDefaultsKey = "certificateArn" | |
static let shared = LiveSynchronizationController() | |
private init() { | |
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: LiveSynchronizationConfiguration.AWSRegion, identityPoolId: LiveSynchronizationConfiguration.CognitoIdentityPoolId) | |
let iotEndPoint = AWSEndpoint(urlString: LiveSynchronizationConfiguration.IOT_ENDPOINT) | |
// Configuration for AWSIoT control plane APIs | |
let iotConfiguration = AWSServiceConfiguration(region: LiveSynchronizationConfiguration.AWSRegion, credentialsProvider: credentialsProvider) | |
// Configuration for AWSIoT data plane APIs | |
let iotDataConfiguration = AWSServiceConfiguration(region: LiveSynchronizationConfiguration.AWSRegion, | |
endpoint: iotEndPoint, | |
credentialsProvider: credentialsProvider) | |
AWSServiceManager.default().defaultServiceConfiguration = iotConfiguration | |
iotManager = AWSIoTManager.default() | |
iot = AWSIoT.default() | |
AWSIoTDataManager.register(with: iotDataConfiguration!, forKey: LiveSynchronizationConfiguration.ASWIoTDataManager) | |
iotDataManager = AWSIoTDataManager(forKey: LiveSynchronizationConfiguration.ASWIoTDataManager) | |
} | |
func subscribe(topic: String) { | |
guard connected else { return } | |
iotDataManager.unsubscribeTopic(self.topic) | |
self.topic = topic | |
iotDataManager.subscribe(toTopic: self.topic, qoS: .messageDeliveryAttemptedAtMostOnce, messageCallback: { (payloadData) -> Void in | |
let json = JSON(payloadData) | |
log("Receive message from server: \(json)") | |
NotificationCenter.default.post(name: Notification.Name.serverChangedBabyEvents, object: nil) | |
}) | |
} | |
func connect() { | |
guard !connected else { return } | |
guard getCertificateIdFromUserDefaults() == nil else { | |
connectToDataManager() | |
return | |
} | |
createCertificateAndConnect() | |
} | |
func disconnect() { | |
guard connected else { return } | |
log("Disconnecting...") | |
DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async { | |
self.iotDataManager.disconnect() | |
NotificationCenter.default.post(name: .liveSynchronizationDisconnected, object: nil) | |
self.connected = false | |
log("Disconnected") | |
} | |
} | |
private func createCertificateAndConnect() { | |
iotManager.createKeysAndCertificate(fromCsr: csrDictionary(), callback: { [weak self] (response) -> Void in | |
guard let responseObject = response, | |
let strongSelf = self else { | |
CrashlyticsNonFatal().record(for: .AWSIoTCreateKeysAndCertificate, description: "Unable to create keys and/or certificate") | |
return | |
} | |
UserDefaults.standard.set(responseObject.certificateId, forKey: strongSelf.certificateIdUserDefaultsKey) | |
UserDefaults.standard.set(responseObject.certificateArn, forKey: strongSelf.certificateArnUserDefaultsKey) | |
let attachPrincipalPolicyRequest = AWSIoTAttachPrincipalPolicyRequest() | |
attachPrincipalPolicyRequest?.policyName = LiveSynchronizationConfiguration.PolicyName | |
attachPrincipalPolicyRequest?.principal = response?.certificateArn | |
// Attach the policy to the certificate | |
strongSelf.iot.attachPrincipalPolicy(attachPrincipalPolicyRequest!).continueWith(block: { (task) -> AnyObject? in | |
if let error = task.error { | |
CrashlyticsNonFatal().record(for: .AWSIoTAttachPrincipalPolicy, description: error.localizedDescription) | |
return nil | |
} | |
DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: { | |
strongSelf.connectToDataManager() | |
}) | |
return nil | |
}) | |
}) | |
} | |
private func csrDictionary() -> [String: String] { | |
return [ | |
"commonName": LiveSynchronizationConfiguration.CertificateSigningRequestCommonName, | |
"countryName": LiveSynchronizationConfiguration.CertificateSigningRequestCountryName, | |
"organizationName": LiveSynchronizationConfiguration.CertificateSigningRequestOrganizationName, | |
"organizationalUnitName": LiveSynchronizationConfiguration.CertificateSigningRequestOrganizationalUnitName, | |
] | |
} | |
private func connectToDataManager() { | |
guard let certificateId = getCertificateIdFromUserDefaults() else { | |
return | |
} | |
iotDataManager.connect(withClientId: UUID().uuidString, | |
cleanSession: true, | |
certificateId: certificateId, | |
statusCallback: mqttEventCallback) | |
} | |
private func getCertificateIdFromUserDefaults() -> String? { | |
return UserDefaults.standard.string(forKey: certificateIdUserDefaultsKey) | |
} | |
private func mqttEventCallback(_ status: AWSIoTMQTTStatus) { | |
DispatchQueue.main.async { | |
log("connection status = \(status.rawValue)") | |
switch status { | |
case .connecting: | |
log("Connecting...") | |
case .connected: | |
self.connected = true | |
log("Connected. Using certificate:") | |
log(self.getCertificateIdFromUserDefaults() ?? "") | |
NotificationCenter.default.post(name: .liveSynchronizationConnected, object: nil) | |
case .disconnected: | |
NotificationCenter.default.post(name: .liveSynchronizationDisconnected, object: nil) | |
log("Disconnected") | |
case .connectionRefused: | |
NotificationCenter.default.post(name: .liveSynchronizationDisconnected, object: nil) | |
log("Connection Refused") | |
case .connectionError: | |
NotificationCenter.default.post(name: .liveSynchronizationDisconnected, object: nil) | |
log("Connection Error") | |
case .protocolError: | |
NotificationCenter.default.post(name: .liveSynchronizationDisconnected, object: nil) | |
log("Protocol Error") | |
default: | |
NotificationCenter.default.post(name: .liveSynchronizationDisconnected, object: nil) | |
log("Unknown state: \(status.rawValue)") | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment