Closed clipchak closed 3 years ago
Hi @clipchak Thanks for reaching out
To Reproduce Steps to reproduce the behavior:
- Go to '...'
- Click on '....'
- Scroll down to '....'
- See error
Hi @ruiguoamz thank you for the reply. Could you specify what you mean when you ask how IoT is configured in AWS IoT console?
Also, to reproduce the issue we are seeing, this issue occurs when our application hasn't been built and ran for an unspecified amount of time (at least 30 minutes). To describe this issue more specifically, the registerToAwsIoT() and connectingToAwsIoT() methods in my post above are called in our application after following a series of methods:
/// Called once to retrieve a user.
private func initializeAwsMobileClient() {
AWSMobileClient.default().initialize { (userState, error) in
if let userState = userState {
switch userState {
case .signedIn:
CognitoService.shared.configureUserAndIdentityPools()
self.connectToAPIGatewayOnSignIn()
...........
}
We call this above method to initialize the AWS mobile client. Once the user is signed in, we configure the user and identity pools with this following method:
// Creates and configures credentials and configuration for cognito.
public func configureUserAndIdentityPools() {
// set up user pool
let userPoolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: AWSConstants.CLIENT_ID, clientSecret: AWSConstants.CLIENT_SECRET, poolId: AWSConstants.USER_POOL_ID)
let pool = AWSCognitoIdentityUserPool(forKey: "UserPool")
// create credentials and configuration
let credentials = AWSCognitoCredentialsProvider(regionType: .USEast2, identityPoolId: AWSConstants.IDENTITY_POOL_ID, unauthRoleArn: AWSConstants.UNAUTH_ROLE_ARN, authRoleArn: AWSConstants.AUTH_ROLE_ARN, identityProviderManager: pool)
let configuration = AWSServiceConfiguration(region:.USEast2, credentialsProvider: credentials)
userCredentials = credentials
userConfiguration = configuration
// register user pool
AWSCognitoIdentityUserPool.register(with: configuration, userPoolConfiguration: userPoolConfiguration, forKey: "UserPool")
AWSServiceManager.default()?.defaultServiceConfiguration = configuration
}
/// Creates the connection to API Gateway if user is signedIn.
private func connectToAPIGatewayOnSignIn() {
// Check user attributes
CognitoService.shared.checkAndUpdateUserCustomAttributes { (result) in
switch result {
case .success(()):
AWSNetworkManager.shared.registerToAwsIot()
AWSNetworkManager.shared.connectingToAwsIoT()
.........
..........
}
}
}
In the successful case, the registerToAwsIot and connectingToAwsIot methods are called
/// Registers a configuration to IoT.
internal func registerToAwsIot() {
guard let userConfiguration = CognitoService.shared.userConfiguration else { logDebugger("User Configuration Nil."); return }
guard let userCredentials = CognitoService.shared.userCredentials else { logDebugger("User Credentials Nil."); return }
// Initialising AWS IoT And IoT DataManager
AWSIoT.register(with: userConfiguration, forKey: "kAWSIoT")
let iotEndpoint = AWSEndpoint(urlString: MQTT.ENDPOINT)
let iotDataConfiguration = AWSServiceConfiguration(
region: .USEast2,
endpoint: iotEndpoint,
credentialsProvider: userCredentials)
AWSIoTDataManager.register(with: iotDataConfiguration!, forKey: "kDataManager")
}
/// Creates a connection to IoT using web sockets.
internal func connectingToAwsIoT() {
let uuid = UUID().uuidString
let dataManager = AWSIoTDataManager(forKey: "kDataManager")
let response = dataManager.connectUsingWebSocket(withClientId: uuid, cleanSession: true, statusCallback: self.mqttEventCallback(_:))
if response != true {
logDebugger("Error connecting to IoT Data manager.")
}
}
Hi @ruiguoamz ,
After further investigation, the issue seems to be regarding sessions. When the app has been sitting for 15 minutes or so and the session expires, the calls to IoT are ignored. However if the app is terminated or a user logs out and logs back in, it works perfectly fine. The solutions i've tried were trying to use the AWSMobileClient.default.initialize() method which worked when ApiGateway had a similar issue. In the case of IoT it does not. The reason we know it is not working is because the mqttCallback method isn't being called, when it is called IoT is connected. There is also no error's being printed or resulting in opening of the application. Is there some method that has to be implemented before calling or initializing IoT in order to make it work when there a session expired?
Steps to Reproduce this error: Have the application sitting long enough where the session expires (about 15 or so minutes, 20 to be safe) Try connecting to IoT and see if the mqttCallback method is called If IoT is setup try making a call to it and monitoring if it is being sent
After the first time of initializing, any subsequent times it will succeed.
If you have further questions please ask. Thank You!
Closed, the issue was that occasionally our data manager was being retrieved before it was properly initialized.
Describe the bug: In iOS 13+, when our application has not been built and ran for a certain amount of time, AWS IoT Data Manager occasionally has a connection status of AWSIoTMQTTStatusUnknown. MQTT connectUsingWebSocket then does not return any status callback. This issue only occurs after our application has not been built and ran for an extended amount of time and never occurs on successive runs of our application.
Which AWS service(s) are affected? AWS-iOT
Expected behavior: AWSIoTDataManager should register and connect to web socket with a status that is connected and not unknown. Calling connectUsingWebSocket should register an mqttEventCallback that prints connecting and then connected. Instead, occasionally connectUsingWebSocket does not return any mqttEventCallback and the connection status of our data manager ends up as AWSIoTMQTTStatusUnknown.
Environment: SDK Version: 2.24 (latest version) Dependency Manager: Pods Swift Version: 5.0+ Xcode Version: 12+
Device Information: Device: iPhone iOS Version: 13+
Sample Code
Example of retrieving data manager and getting a connection status