Я разрабатываю приложение для iOS с использованием AWS IoT Core и MQTT для управления устройствами Smart Home. Каждое устройство имеет соответствующую AWS IoT Thing », а приложение подписывается на тень Delta Delta по теме каждой вещи: < /p>
$aws/things//shadow/update/delta
< /code>
Примечание: эта проблема возникает только в приложении iOS. Та же самая логика отлично работает в приложении Android с 80+ вещами. Эти устройства на самом деле находятся в Интернете, но их сообщения Shadow Delta никогда не появляются. func createIOTConnection()
{
if timer.isValid {
timer.invalidate()
}
if InternetConnectionManager.shared.checkInternetConnection() {
print("iot* createIOTConnection")
count = 0
let uuid = UUID().uuidString
print("iot* uuid \(uuid)")
debugPrint("ITC: MQTT Client UUID: \(uuid)")
iotDataManager.connectUsingWebSocket(withClientId: uuid, cleanSession: true) { (connectionStatus) in
switch connectionStatus {
case .unknown:
print("iot* unknown")
self.showBannerWithMsg(msg: "Connecting")
case .connecting:
print("iot* connecting")
self.showBannerWithMsg(msg: "Connecting")
case .connected:
print("iot* connected")
self.showBannerWithMsg(msg: "Connected")
self.subscribeForDelta()
self.subscribeToAllModules(true)
self.delegate?.connectedToIoT?()
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "iotConnected"), object: nil, userInfo: nil)
case .disconnected:
print("iot* disconnected")
self.showBannerWithMsg(msg: "Connecting")
case .connectionRefused:
print("iot* connectionrefused")
case .connectionError:
print("iot* connectionerror")
self.showBannerWithMsg(msg: "Connecting")
case .protocolError:
print("iot* protocolerror")
}
}
timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(continuousCheckForIOTConnection), userInfo: nil, repeats: true)
}
else {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(checkIfInternetIsAvailable), userInfo: nil, repeats: true)
}
}
func subscribeToAllModules(_ getStatus:Bool)
{
if UserDefaults.standard.bool(forKey: "isLoggedIn")
{
DispatchQueue.global().async {
let array = dbManager.fetchList(query: "select serialNumber from master", columnName: "serialNumber", .master) as! [String]
////print(array)
for srnum in array {
self.subscribeWithSerialnumber(serialnumber: srnum, operation: .update)
if srnum.contains("zdp") {
self.subscribeWithSerialnumber(serialnumber: srnum, operation: .get)
}
// if !srnum.contains("1001") {
// self.subscribeWithSerialnumber(serialnumber: srnum, operation: .update)
// if srnum.contains("zdp") {
// self.subscribeWithSerialnumber(serialnumber: srnum, operation: .get)
// }
// } else {
// print("Condition failed")
// }
}
if getStatus && !isSceneExecuting {
let modules = dbManager.fetchData("select serialNumber,moduleType from master", .master)
modules.forEach { (module) in
let dict = Module_Data.getActiveModuleGroupsWithApplianceCount(moduleString: module["moduleType"]! as! String)
if dict.keys.contains("LI") || dict.keys.contains("DL") || dict.keys.contains("FA") || dict.keys.contains("PM") || dict.keys.contains("CM") {
let srnum = module["serialNumber"]! as! String
if (RoomDetails.roomExecution != nil && !RoomDetails.roomExecution.sentSerialNumbers.contains(srnum)) || RoomDetails.roomExecution == nil {
// debugPrint("sent ping msg to \(srnum)")
self.updateThing(thingname: srnum, json: self.pingMsg, shadowOperation: .update)
}
}
}
//
//
// array = dbManager.fetchList(query: "select serialNumber from master where moduleType like '%SS00%' and moduleType like '%LK00%' and moduleType like '%WL00%' and moduleType like '%WR00%'", columnName: "serialNumber", .master) as! [String]
// for srnum in array {
//
// }
}
}
}
}
func subscribeForDelta() {
if let email = UserDefaults.standard.string(forKey: "email") {
self.subscribeWithSerialnumber(serialnumber: email.alphanumeric, operation: .get)
self.updateThing(thingname: email.alphanumeric, json: "", shadowOperation: .get)
let topic = "$aws/things/\(email.alphanumeric)/shadow/update/delta"
debugPrint("ITC: Subscribing for delta topic: \(topic)")
let subscribed = iotDataManager!.subscribe(toTopic: topic, qoS: .messageDeliveryAttemptedAtMostOnce) { (data) in
debugPrint("ITC: Delta payload received")
debugPrint(data)
do {
let d = try JSONSerialization.jsonObject(with: data, options: []) as! Dictionary
self.identifyDelta(devices: d["state"] as! Dictionary)
} catch {
////print("exception \(error)")
}
}
debugPrint("ITC: Delta topic subscription success: \(subscribed)")
}
}
func subscribeWithSerialnumber(serialnumber : String, operation: ShadowOperation) {
let topic = "$aws/things/\(serialnumber)/shadow/\(operation.rawValue)/accepted"
// ////print(topic)
debugPrint("ITC: Subscribing to topic: \(topic)")
// iotDataManager.subscribe(toTopic: topic, qoS: .messageDeliveryAttemptedAtMostOnce) { (obj, str, data) in
// }
let result = iotDataManager . subscribe (toTopic: topic, qoS: .messageDeliveryAttemptedAtMostOnce) {
(data) in
debugPrint("ITC: Received MQTT message for \(serialnumber):")
debugPrint(data)
do {
let d = try JSONSerialization.jsonObject(
with: data,
options:[]) as!Dictionary
debugPrint("ITC: subscribeWithSerialnumber Full JSON shadow response:")
debugPrint(d)
let state = d ["state"] as ! Dictionary < String, Any>
debugPrint(state)
let reported = state ["reported"]
if let delta = state ["delta"] as? [ String : String] {
if let emailId = UserDefaults . standard . string (forKey: "email") {
if emailId.alphanumeric == serialnumber {
self.identifyDelta(devices: delta)
if operation == . get {
self.unsubscribeToSerialnumber(
serialnumber: serialnumber,
shadowOperation:.get)
}
}
}
}
if (reported != nil && UserDefaults.standard.string(forKey: "email")?.alphanumeric != serialnumber)
{
// if serialnumber.contains("zdp") {
//
// }
print("\(reported!) \(serialnumber)")
let reportedDict = reported as!Dictionary
if operation == . get {
if serialnumber.contains("zdp") && reportedDict.keys.contains("ZBSEQ") {
UserDefaults.standard.setValue(
reportedDict["ZBSEQ"]
!as
!String,
forKey: "ZBSEQ-\(serialnumber)")
}
self.delegate?.getAck?(response: reportedDict, serialNumber: serialnumber)
}
else if operation == . update && !(reportedDict.keys.count == 1 && Array(reportedDict.keys)[0].contains("ACParams"))
{
self.saveResponseForSerialNumber(
serialnumber: serialnumber,
response: reportedDict,
version: String
(describing: d
["version"]
!
), timestamp: String(describing: d["timestamp"]!))
}
else if (reportedDict.keys.count == 1 && Array(reportedDict.keys)[0].contains("ACParams")) {
self.parseResponseForGet(serialNumber: serialnumber, reported: reportedDict)
}
if serialnumber.contains("slm") {
self.saveLockResponse(reportedDict, serialnumber)
}
}
} catch {
////print("exception \(error)")
debugPrint("JSON Parse Error:")
debugPrint(error)
}
}
// if result {
// debugPrint("subscribed to \(serialnumber)")
// }
// else {
// debugPrint("not subscribed to \(serialnumber)")
// }
< /code>
} < /p>
endension йотконнекция {< /p>
open func getShadow(_ serialNumber:String) {
debugPrint("DEBUG: ITC: getShadow called for serialNumber: \(serialNumber)")
let getRequest = AWSIoTDataGetThingShadowRequest()
getRequest?.thingName = serialNumber
let iotData = AWSIoTData(forKey: "IoTData")
iotData.getThingShadow(getRequest!) { (response, err) in
if let response = response {
debugPrint("ITC: getThingShadow response received for \(serialNumber).")
do {
guard let payloadData = response.payload as? Data else {
debugPrint("ITC: getShadow payload is not Data type or is nil.")
return
}
let d = try JSONSerialization.jsonObject(with: payloadData, options: []) as! Dictionary
debugPrint("ITC: getShadow JSON parsing successful for \(serialNumber).")
guard let state = d["state"] as? Dictionary else {
debugPrint("ITC: getShadow 'state' key missing or not a dictionary in response for \(serialNumber).")
return
}
guard let reported = state["reported"] else {
debugPrint("ITC: getShadow 'reported' key missing in 'state' for \(serialNumber).")
return
}
debugPrint("ITC: getShadow Full JSON shadow response for \(serialNumber):")
debugPrint(d)
if(reported != nil && UserDefaults.standard.string(forKey: "email")?.alphanumeric != serialNumber) {
debugPrint("ITC: getShadow reported is not nil and serialNumber condition met for \(serialNumber).")
guard let reportedDict = reported as? Dictionary else {
debugPrint("ERROR: ITC:ITC: getShadow 'reported' is not a dictionary for \(serialNumber).")
return
}
if serialNumber.contains("zdp") && reportedDict.keys.contains("ZBSEQ") {
debugPrint("ITC: getShadow serialNumber contains 'zdp' and reportedDict contains 'ZBSEQ'. Saving ZBSEQ for \(serialNumber).")
UserDefaults.standard.setValue(reportedDict["ZBSEQ"]! as! String, forKey: "ZBSEQ-\(serialNumber)")
}
self.delegate?.getAck?(response: reportedDict, serialNumber: serialNumber)
debugPrint("ITC: getAck delegate called for \(serialNumber).")
if (reportedDict.keys.count == 1 && Array(reportedDict.keys)[0].contains("ACParams")) {
debugPrint("ITC: getShadow reportedDict contains only 'ACParams'. Calling parseResponseForGet for \(serialNumber).")
self.parseResponseForGet(serialNumber: serialNumber, reported: reportedDict)
}
} else {
debugPrint("ITC: getShadow reported is nil or serialNumber condition not met for \(serialNumber). Reported: \(reported == nil ? "nil" : "present"), User email alphanumeric: \(UserDefaults.standard.string(forKey: "email")?.alphanumeric ?? "nil"), SerialNumber: \(serialNumber).")
}
} catch {
debugPrint("ITC: getShadow JSON deserialization error for \(serialNumber): \(error.localizedDescription)")
}
} else {
debugPrint("ITC: getThingShadow request failed for \(serialNumber): \(err?.localizedDescription ?? "Unknown Error").")
}
}
}
}
// MARK: get or update thing
func updateThing(thingname: String, json: String, shadowOperation:ShadowOperation) {
print("# update thing \(json) for thingname \(thingname)")
let topic = "$aws/things/\(thingname)/shadow/\(shadowOperation.rawValue)"
// debugPrint(json)
iotDataManager.publishString(json, onTopic: topic, qoS: .messageDeliveryAttemptedAtMostOnce)
debugPrint("ITC: Publishing to: $aws/things/\(thingname)/shadow/\(shadowOperation.rawValue)")
debugPrint("ITC: Payload: \(json)")
}
< /code>
Приложение использует Awsiotdatamanager для MQTT и FMDB для локального хранилища SQLite.
Shadow Deltas используются для запуска обновлений состояний. Задержка).
Попытки подписки на ведение журнала. На сколько теневых тем может быть подписано одновременно? Темы в iOS? Та же самая логика отлично работает в приложении Android с 80+ вещами.
Подробнее здесь: https://stackoverflow.com/questions/796 ... r-50-thing
AWS IOT MQTT: устройства случайно показывают как автономный режим при подписке на более чем 50 вещей в приложении iOS ⇐ IOS
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Как я могу исправить ошибку EOF в нарушение протокола (_SSL.C: 2393) с AWS IOT и MQTT
Anonymous » » в форуме Python - 0 Ответы
- 2 Просмотры
-
Последнее сообщение Anonymous
-