-
Notifications
You must be signed in to change notification settings - Fork 886
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IoT disconnected after token expired, auto refresh token is working #4191
Comments
I see you are directly using a We have a sample project which you can reference. First, see how the credentials provider is created. (code) It is passed into Below is an example of sections you can define in "IoT": {
"Default": {
"Region": "us-east-1",
"Endpoint": "https://iot.us-east-1.amazonaws.com"
}
},
"IoTManager": {
"Default": {
"Region": "us-east-1",
"Endpoint": "https://iot.us-east-1.amazonaws.com"
}
},
"IoTDataManager": {
"Default": {
"Region": "us-east-1",
"Endpoint": "https://REPLACE-ats.iot.us-east-1.amazonaws.com"
}
}, Below is some reference code you can use as well. It loads these sections from // MARK: - Control Plane setup
guard let iotServiceInfo = AWSInfo.default().serviceInfo("IoT", forKey: "Default"),
let iotManagerServiceInfo = AWSInfo.default().serviceInfo("IoTManager", forKey: "Default"),
let iotDataManagerServiceInfo = AWSInfo.default().serviceInfo("IoTDataManager", forKey: "Default") else {
fatalError("Failed to read in default service info for IoT")
}
let iot = AWSIoT.default()
guard let credentialsProvider = iot.configuration.credentialsProvider as? AWSCognitoCredentialsProvider else {
fatalError("App must be configured")
}
let region = iotServiceInfo.region
let controlPlaneServiceConfiguration = AWSServiceConfiguration(region:region, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = controlPlaneServiceConfiguration
iotManager = AWSIoTManager.default()
self.region = region
self.credentialsProvider = credentialsProvider
guard let iotDataManagerEndpoint = iotDataManagerServiceInfo.endpoint else {
fatalError("Failed to get Data Manager endpoint")
}
// MARK: - Data Plane setup
guard let dataConfiguration = AWSServiceConfiguration(region: iotDataManagerServiceInfo.region,
endpoint: iotDataManagerEndpoint,
credentialsProvider: credentialsProvider) else {
fatalError("Failed to create Data Configuration")
}
// Configure MQTT with Last Will & Testament (LWT)
let mqttConfiguration = AWSIoTMQTTConfiguration()
let message = "LWT-\(Date())"
mqttConfiguration.lastWillAndTestament.message = message
mqttConfiguration.lastWillAndTestament.topic = "lwt/disconnected"
mqttConfiguration.lastWillAndTestament.qos = .messageDeliveryAttemptedAtLeastOnce
mqttConfiguration.lastWillAndTestament.willRetain = true
AWSIoTDataManager.register(with: dataConfiguration, with: mqttConfiguration, forKey: Constants.dataManagerKey)
iotDataManager = AWSIoTDataManager(forKey: Constants.dataManagerKey)
// Control Plane
assertEqual(iotServiceInfo.infoDictionary["Endpoint"] as? String, iot.configuration.endpoint.url.absoluteString)
assertEqual(iotManagerServiceInfo.infoDictionary["Endpoint"] as? String, iotManager.configuration.endpoint.url.absoluteString)
// Data Plane
assertEqual(iotDataManagerServiceInfo.infoDictionary["Endpoint"] as? String, iotDataManager.configuration.endpoint.url.absoluteString) This code uses Cognito to support the credentials provider which may meet your needs with not additional requirements. Since you have a lambda doing this work you could create your own implementation of Your implementation will need to refresh the credentials before the current credentials expire so when they are requested they are always current. You could also refresh credentials on demand when they are expired. You will want to ensure this is done once when the token is expiring and make that process thread-safe. |
HI THANKS func mqttEventCallbackWebsocket(_ status: AWSIoTMQTTStatus) {
print("AWS connection status = \(status.rawValue)")
case .connected:
print("Connected to AWS successfully")
switch region {
case .Singapore:
isSingaporeConnectedToAWS = true
case .Sydney:
isSydneyConnectedToAWS = true
case .Japan:
isJapanConnectedToAWS = true
case .China:
isChinaConnectedToAWS = true
case .Virginia:
isVirginiaConnectedToAWS = true
case .California:
isCaliforniaConnectedToAWS = true
case .London:
isLondonConnectedToAWS = true
case .Frankfurt :
isFrankfurtConnectedToAWS = true
}
completionHandler(region)
print("AT connect \(region)")
case .connectionError:
print("AWS IoT connection error")
completionHandler(region)
SetupStatusCallback(err: "err", region: region)
case .connectionRefused:
print("AWS IoT connection refused")
SetupStatusCallback(err: "err", region: region)
completionHandler(region)
case .protocolError:
print("AWS IoT protocol error")
SetupStatusCallback(err: "err", region: region)
completionHandler(region)
case .disconnected:
SetupStatusCallback(err: "err", region: region)
print("AWS disconnected")
completionHandler(region)
case .unknown:
print("AWS unknown connection")
SetupStatusCallback(err: "err", region: region)
completionHandler(region)
default:
print("AWS IoT unknown state")
SetupStatusCallback(err: "err", region: region)
completionHandler(region)
}
/ }
}
func perfromActionforRegion(obj : AWSIoTDataManager?) {
guard let obj = obj else {
let status = obj?.getConnectionStatus()
print("AWS IoT state \(status)")
completionHandler(region)
return
}
//On error
func SetupStatusCallback(err : String,region : Regions){
print("SetupStatusCallback \(err)")
self.initMQQt()
}
func initMQQt(){
AWSAuthManager.shared.getToken{ accessToken in
if accessToken == "error on getting token"{
AWSAuthManager.shared.logoutFromApp()
}
if accessToken == AWSAuthManager.shared.accessToken {
print(" dont need new token")
}
else{
print(" Reconnect Reuired")
self.initializeAWSWithTopic()
AWSAuthManager.shared.accessToken = accessToken
self.connectDeviceToAWS()
}
}
} Trying to reconnect on error but not working fine(some time able to reconnect) Also taking more time |
As per suggestion from IOT coder AWSMobileClient.default().getAWSCredentials { [self] (credentials, error) in
if let error = error {
print("\(error.localizedDescription)")
completionHandler("out")
} else if let credentials = credentials {
self.ProviderManager = CustomIdentityProviderToken(accessKey:credentials.accessKey, secretKey:credentials.secretKey, sessionKey: credentials.sessionKey, expiration: credentials.expiration as NSDate?)
print(credentials.accessKey)
initializeDataPlane { isComplete in
self.connectDeviceToAWS()
completionHandler("done")
}
}
}
|
@JyotsnaPiOSDEV I see you are using |
Problem able to connect but not subscribes why ? |
Can you provide more information like logs to show what is happening? I am not able to determine what is happening from these questions. |
In android on connection error they ate just calling get token .Able to change token and reconnect and subscribe
|
Please add this code when you configure AWS: AWSDDLog.sharedInstance.logLevel = .verbose
AWSDDLog.add(AWSDDTTYLogger()) Then use the console to see what is happening. Share the relevant details on this issue. |
AWSCognitoCredentialsProvider using on launch and on reconnection Initializing MQTTEncoder and MQTTDecoder streams Connecting to AWS IoT Metrics collection is: Enabled so what is wrong in my sequence. |
Can you try using this code? Start out by making sure you initialize the control plane and data plane along with the MQTT configuration. public init() {
#if DEBUG
AWSDDLog.sharedInstance.logLevel = .verbose
AWSDDLog.add(AWSDDTTYLogger())
#endif
// MARK: - Control Plane setup
guard let iotServiceInfo = AWSInfo.default().serviceInfo("IoT", forKey: "Default"),
let iotManagerServiceInfo = AWSInfo.default().serviceInfo("IoTManager", forKey: "Default"),
let iotDataManagerServiceInfo = AWSInfo.default().serviceInfo("IoTDataManager", forKey: "Default") else {
fatalError("Failed to read in default service info for IoT")
}
#if DEBUG
print("IoT: \(iotServiceInfo.infoDictionary["Endpoint"] ?? "")")
print("IoT Manager: \(iotManagerServiceInfo.infoDictionary["Endpoint"] ?? "")")
print("IoT Data Manager: \(iotDataManagerServiceInfo.infoDictionary["Endpoint"] ?? "")")
#endif
let iot = AWSIoT.default()
guard let credentialsProvider = iot.configuration.credentialsProvider as? AWSCognitoCredentialsProvider else {
fatalError("App must be configured")
}
let region = iotServiceInfo.region
let controlPlaneServiceConfiguration = AWSServiceConfiguration(region:region, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = controlPlaneServiceConfiguration
iotManager = AWSIoTManager.default()
self.region = region
self.credentialsProvider = credentialsProvider
// MARK: - Data Plane setup
guard let iotDataManagerEndpoint = iotDataManagerServiceInfo.endpoint else {
fatalError("Failed to get Data Manager endpoint")
}
guard let dataConfiguration = AWSServiceConfiguration(region: iotDataManagerServiceInfo.region,
endpoint: iotDataManagerEndpoint,
credentialsProvider: credentialsProvider) else {
fatalError("Failed to create Data Configuration")
}
// Configure MQTT with Last Will & Testament (LWT)
let mqttConfiguration = AWSIoTMQTTConfiguration()
let message = "LWT-\(Date())"
mqttConfiguration.lastWillAndTestament.message = message
mqttConfiguration.lastWillAndTestament.topic = "lwt/disconnected"
mqttConfiguration.lastWillAndTestament.qos = .messageDeliveryAttemptedAtLeastOnce
mqttConfiguration.lastWillAndTestament.willRetain = true
AWSIoTDataManager.register(with: dataConfiguration, with: mqttConfiguration, forKey: Constants.dataManagerKey)
iotDataManager = AWSIoTDataManager(forKey: Constants.dataManagerKey)
// Control Plane
assertEqual(iotServiceInfo.infoDictionary["Endpoint"] as? String, iot.configuration.endpoint.url.absoluteString)
assertEqual(iotManagerServiceInfo.infoDictionary["Endpoint"] as? String, iotManager.configuration.endpoint.url.absoluteString)
// Data Plane
assertEqual(iotDataManagerServiceInfo.infoDictionary["Endpoint"] as? String, iotDataManager.configuration.endpoint.url.absoluteString)
} This is the function to connect.
See that it does not pass in In the |
Result - print("Failed to read in default service info for IoT") |
You need to define each of the IoT sections in "IoT": {
"Default": {
"Region": "us-east-1",
"Endpoint": "https://iot.us-east-1.amazonaws.com"
}
},
"IoTManager": {
"Default": {
"Region": "us-east-1",
"Endpoint": "https://iot.us-east-1.amazonaws.com"
}
},
"IoTDataManager": {
"Default": {
"Region": "us-east-1",
"Endpoint": "https://CHANGE_ME-ats.iot.us-east-1.amazonaws.com"
}
}, |
All configuration done 2022-07-11 13:21:15:085 Votion Home[7211:205865] [SR] NSStreamEventOpenCompleted <__NSCFInputStream: 0x7b24000192c0> 2022-07-11 13:21:15:086 Votion Home[7211:205865] [SR] NSStreamEventOpenCompleted <__NSCFOutputStream: 0x7b2400019980> 2022-07-11 13:21:31:084 Votion Home[7211:206261] [SR] NSStreamEventOpenCompleted <__NSCFOutputStream: 0x7b2400038370> |
Our team is trying to look into the issue and will provide an update soon. |
For connecting to MQTT channel of AWS IOT core we are using custom auth lambda for policy generation.
In custom auth lambda we are using access token of AWS cognito to authenticate request.
I want to reconnect on dissconect
Which AWS Services are you utilizing?
AWSIoT
SDK Version: 2.270.
Dependency Manager: Cocoapods
Device: Any device
iOS Version: Any version
Please help how to reconnect and fix this disconnect issue
The text was updated successfully, but these errors were encountered: