MQTT does not connect at all, always disconnects - ios

I have been trying to connect mqtt to my mqtt Server using 3.1, but i am unable to do so. here is my code :
i am using Cocoa MQTT for this:
mqtt = CocoaMQTT(clientID: clientId, host: server, port: UInt16(port))
mqtt.username = ""
mqtt.password = password
self.mqtt.delegate = self
mqtt.connect()
Only disconnect and status change delegate called, other delegates never get called.
When I set loglevel to debug
it only prints:
CocoaMQTT(info): Connected to 18.194.27.95 : 8000
CocoaMQTT(debug): Socket write message with tag: 0
and only status change and disconnect delegate get called.

Related

Resubscribing to MQTT Topic when Network ist Lost

I have developed a Quarkus app with which I want to receive and process MQTT messages.
This also works so far.
My problem is that when the internet goes down at the MQTT broker and the app reconnects afterwards, the app reconnects to the broker but no messages are received. I think that the "subscribe" method is not called anymore.
How can I solve this problem?
Here is my Config:
mp.messaging.incoming.smarthome/electricity.connector=smallrye-mqtt
mp.messaging.incoming.smarthome/electricity.host=192.168.1.88
mp.messaging.incoming.smarthome/electricity.port=1883
mp.messaging.incoming.smarthome/electricity.reconnect-attempts=3000
mp.messaging.incoming.smarthome/electricity.reconnect-interval-seconds=10
mp.messaging.incoming.smarthome/electricity.qos=1
mp.messaging.incoming.smarthome/electricity.failure-strategy=ignore
Here is my Controller:
#Incoming("smarthome/electricity")
public void consume(byte[] raw) {
String price = new String(raw,StandardCharsets.UTF_8);
String[] parts = price.split(",");
String watt = parts[0].trim();
String timeStamp = parts[1].trim();
byte wattH = Byte.parseByte(watt.replace("WH", ""));
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Europe/Vienna"))
.withHour(Integer.parseInt(timeStamp.split(":")[0]))
.withMinute(Integer.parseInt(timeStamp.split(":")[1]));
Message message = new Message(wattH,now);
System.out.println(message);
service.addToPackage(message);
scheudler.check();
}
Stack Output if i cut the Connection:
2022-09-20 07:50:09,683 ERROR [io.sma.rea.mes.mqtt] (vert.x-eventloop-thread-0) SRMSG17105: Unable to establish a connection with the MQTT broker: java.net.SocketException: Connection reset
If the Connection is back:
2022-09-20 07:50:26,751 INFO [io.ver.mqt.imp.MqttClientImpl] (vert.x-eventloop-thread Connection with 192.168.1.88:1883 established successfully
So the connection seems to be back, but there are no more incoming messages.
I solved the Problem by myself.
I set :
quarkus.arc.remove-unused-beans=none
And now it works fine.
I tried many ways to fix the problem, but this seems to be the issue.
I think there is some bean removed in the runtime when the connection is lost for a too long time.
If anyone can explain why this happens please tell me

Socket-io iOS client says it's connected to server, despite "connection" event not firing on the server

I am having trouble wrapping my mind around this problem with my very basic Socket-IO setup. In short, the iOS client (running Socket.IO-Client-Swift), seems convinced that it has successfully connected to the socket on the server: The SocketIOClient has a status of connected. However, on the server the connection event is never fired.
When running the code below the iOS client prints Socket status: connected to the console once every 15 seconds or so, indicating that it has successfully connected to the server, and that the connection is maintained.
However, on the server, it appears that the "connection" event is never fired. NEW CONNECTION is never printed to the console on the server. The only console output is Server is running on port 4400..., indicating that the server is ready to accept connections.
When attempting to connect to the server via a web browser, NEW CONNECTION is printed to the console of the server, as expected. It appears that the problem is with the iOS code.
The complete code for the client and server is below.
Client:
class GMSockets {
private var manager: SocketManager = SocketManager(socketURL: URL(string: "ws://localhost:4400")!, config: [.log(false), .compress])
private var socket: SocketIOClient
init() {
self.socket = self.manager.defaultSocket
self.socket.on(clientEvent: .connect) { (data, ack) in
print("Socket status: \(self.socket.status)")
self.socket.emit("testEvent", "Hello")
}
self.socket.connect()
}
}
Server:
let port = 4400;
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(port);
console.log(`Server is running on port ${port}...`);
io.sockets.on("connection", function(socket) {
console.log("NEW CONNECTION")
socket.on("testEvent", function(data) {
console.log("Test event recieved")
})
})
I am using Socket.IO-Client-Swift version 15.2.0 on the iOS client, and Socket.io version 3.0.4 on the server.
The documentation for Socket.IO-Client-Swift erroneously suggests that it supports Socket-io 3.0, however it only supports versions 2.x.x. Downgrading socket.io to 2.3.0 (the last 2.x.x release) will fix this issue.

"Tried connecting on an already connected socket" - Socket.IO-Client-Swift

I am using swift 4 and Socket.IO-Client-Swift, '~>13.1.1' (latest version).
I tried to call socket.connect() after adding socket handlers but I was getting an error "Tried connecting socket when engine isn't open". So I have added socket.connect() code inside a timer and calling it after 5 seconds, so engine was already opened by that time and not getting that error anymore.
But now I am getting the error "Tried connecting on an already connected socket", even though connect client event handler was never called.
I have gone through the documentation and all the issues that were posted on git but no explanation on how to solve this or why this error even occurs.
You can find the code and console log below.
let manager = SocketManager(socketURL: URL(string: "https://socket.******.**")!, config: [.log(true),.connectParams(["token":Utils.getToken()]),.reconnects(true)])
socket = manager.socket(forNamespace: "/**********")
console log:
2018-02-01 02:20:00.810496+0530 *******[2476:1630437] LOG SocketIOClient{/**********}: Adding handler for event: connect
2018-02-01 02:20:00.837403+0530 *******[2476:1630437] LOG SocketIOClient{/**********}: Adding handler for event: message
2018-02-01 02:20:00.838168+0530 *******[2476:1630437] LOG SocketManager: Manager is being released
2018-02-01 02:20:05.815458+0530 *******[2476:1630437] LOG SocketIOClient{/**********}: Tried connecting on an already connected socket
From the console log, you can see that I am getting "Manager is being released" error msg. Is there a way to retain the manager object? Is that the main reason behind this issue?
Sockets created through the manager are retained by the manager. So at the very least, a single strong reference to the manager must be maintained to keep sockets alive. (As per docs, https://nuclearace.github.io/Socket.IO-Client-Swift/Classes/SocketManager.html)
Easiest way to fix this is create singleton class to retain the manager object
open class SocketConnection {
open static let `default` = SocketConnection()
private let manager: SocketManager
private var socket: SocketIOClient
private init() {
manager = SocketManager(socketURL: URL(string: "https://socket.******.**")!, config: [.log(true),.connectParams(["token":Utils.getToken()]),.reconnects(true)])
socket = manager.socket(forNamespace: "/**********")
}
}

Connecting to MQTT happens after publish due to async

I'm using CocoaMQTT to connect and publish events. To publish, its important that I am connected to MQTT. But connect is async and so is publish. I want it to be sequential that first it should connect and once connected then publish so for example if the connect happens after 5mins then publish should happen after that.
https://github.com/emqtt/CocoaMQTT
How exactly can I do that?
Here is my code:
class ViewController: UIViewController {
var iot: MQTTDelegate!
#IBAction func click(_ sender: Any) {
self.iot = IoT(
withClientId: "clientId",
host: "host",
port: 1883
)
iot.connect(username: "username", password: "token")
iot.publish(topic: "hello", message: "")
}
}
If I move connect to a separate button then it works as first I click the connect button and then I click the "click" button so its sequential. How do I make the above code sequential?
I used PromiseKit to promisify the code but I dont know what exactly to fulfill to connect.
It looks like you are trying to establish a connection to an MQTT server and publish a message to a topic, but the connection is being established after the message is published due to asynchronous behavior.
To fix this issue, you can use the connect() method of the MQTTClient class to establish the connection before publishing the message. The connect() method takes a completion block that is called when the connection is established or if an error occurs.
Here is an example of how you could modify your code to establish the connection before publishing the message:
client.connect { error in
if error == nil {
// Connection was successful
client.publish("topic", withString: "Hello, World!")
} else {
// There was an error connecting to the MQTT server
}
}
This way, the connection to the MQTT server will be established before the message is published, and the message will be sent as soon as the connection is ready.

Keepalive timer on mqtt of nodemcu (esp8266) is not responding

Dears,
I am trying to use mqtt on esp8266 build on nodemcu. I am currently using a custom build (https://nodemcu-build.com/index.php)
modules used: adc,enduser_setup,file,gpio,http,mqtt,net,node,ow,pwm,tmr,uart,wifi
version:powered by Lua 5.1.4 on SDK 1.5.1(e67da894)
function connect_to_mqtt_broker()
print("Connecting to broker...")
m:connect(BROKER, PORT, 0, 1, function(client)
print("connected")
print("["..tmr.time().."(s)] - Client connected to broker: "..BROKER)
m:subscribe(SUB_TOPIC,0, function(conn)
print("Subscribed to "..SUB_TOPIC.." topic")
led(0,204,0,150)
end)
m:publish(PUB_TOPIC,"Hello from: "..node.chipid()..RESTART_REASON,0,0, function(conn)
print("sent")
end)
end,
function(client, reason)
print("failed reason: "..reason)
end)
end
---MQTT client---
print("--------------> Create mqtt clinet")
--set up MQTT client
-- init mqtt client with keepalive timer 120sec
m = mqtt.Client("ESP"..node.chipid(), KEEP_ALIVE_TMR, USER, PASSWORD)
m:lwt(PUB_TOPIC, "offline", 0, 0)
m:on("offline", function(conn)
print("["..tmr.time().."(s)] - Mqtt client gone offline")
end)
m:on("message", function(conn, topic, data)
--receive_data(data, topic)
print("Data received: "..data)
led(200,50,50,30)
receive_data(data, topic)
led(0,204,0,150)
end)
So at the initialization of the of the program I am calling connect_to_mqtt_broker(), which is working perfectly and I can subscribe and publish to topics.
The problem is that the keepalive timer is not correct. Let me explain that with an example. I set KEEP_ALIVE_TMR = 120s and after the esp8266 connected successfully to mqtt broker I disabled the wifi on my router and start counting seconds. According to KEEP_ALIVE_TMR the offline event:
m:on("offline", function(conn)
print("["..tmr.time().."(s)] - Mqtt client gone offline")
end)
should fire exactly 120 seconds from the moment I have disable WiFi, but for some unknown reason this won't happen. Usually the event fires up about 10-15 minutes later.
I am struggling to understand the reason of this delay with no success.
Do you have any ideas why this strange thing happens?
I've also faced with the same issue when autoreconnect flag was set. This flag breaks the run of offline event of connection between broker.
Try it without setting autoreconnect, whose default is 0 :
m:connect(BROKER, PORT, 0, function(client)
If you do your testing by turning your mqtt broker on/off, and it works. But not by switching your wifi connections, then it is the nodemcu's mqtt library problem.
I believe that there is no such mqtt offline/disconnect event on wifi disconnection. Here it is the workaround by add connection's watchdog.
tmr.alarm(1, 3000, 1, function()
if wifi.sta.getip() == nil then
--mark as mqtt restart needed
restart = true
else
-- wifi reconnect detected then restart mqtt connections
if restart == true then
--reset flag, clean object, init for a new one
restart = false
m = nil
mqtt_init()
connect()
end
end
end)
Here it is the full code example

Resources