Skip to content

Instantly share code, notes, and snippets.

@castus
Created April 28, 2018 12:41
Show Gist options
  • Save castus/fea6d241f967d8cc63aeb009142f1c65 to your computer and use it in GitHub Desktop.
Save castus/fea6d241f967d8cc63aeb009142f1c65 to your computer and use it in GitHub Desktop.
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