How to handle failed connections with Flask-MQTT - python

I have a Flask-Mqtt client running, and everything is fine if broker is accessible. The problem starts when the MQTT broker is not accessible. Usually, I would be able to handle the failed connections with exceptions on the on_connect function, however I don't quite understand how to implement it with Flask-Mqtt
I would want to handle failed broker connections while allowing the web server to run the web pages.
Documentations and example of Flask-MQTT: https://flask-mqtt.readthedocs.io/en/latest/usage.html
The code for handling broker connection failure (based on Steve's Internet Guide)
def on_connect(client, userdata, flags, rc):
if rc==0:
client.connected_flag=True #set flag
print("connected OK")
else:
print("Bad connection Returned code=",rc)
client.bad_connection_flag=True
The error on Flask app when broker not connected:
C:\Users\USER\Documents\College\FYP1\flask_testing\venv\Scripts\python.exe C:/Users/USER/Documents/College/FYP1/flask_testing/main.py
Traceback (most recent call last):
File "C:/Users/USER/Documents/College/FYP1/flask_testing/main.py", line 37, in <module>
mqtt = Mqtt(app)
File "C:\Users\USER\Documents\College\FYP1\flask_testing\venv\lib\site-packages\flask_mqtt\__init__.py", line 104, in __init__
self.init_app(app)
File "C:\Users\USER\Documents\College\FYP1\flask_testing\venv\lib\site-packages\flask_mqtt\__init__.py", line 183, in init_app
self._connect()
File "C:\Users\USER\Documents\College\FYP1\flask_testing\venv\lib\site-packages\flask_mqtt\__init__.py", line 209, in _connect
res = self.client.connect(
File "C:\Users\USER\Documents\College\FYP1\flask_testing\venv\lib\site-packages\paho\mqtt\client.py", line 941, in connect
return self.reconnect()
File "C:\Users\USER\Documents\College\FYP1\flask_testing\venv\lib\site-packages\paho\mqtt\client.py", line 1075, in reconnect
sock = self._create_socket_connection()
File "C:\Users\USER\Documents\College\FYP1\flask_testing\venv\lib\site-packages\paho\mqtt\client.py", line 3546, in _create_socket_connection
return socket.create_connection(addr, source_address=source, timeout=self._keepalive)
File "C:\Users\USER\AppData\Local\Programs\Python\Python38\lib\socket.py", line 807, in create_connection
raise err
File "C:\Users\USER\AppData\Local\Programs\Python\Python38\lib\socket.py", line 796, in create_connection
sock.connect(sa)
socket.timeout: timed out

I faced a similar error. Everything was working fine when the mqtt server was running but if I started the app with the server switched off, the app failed with the same message than yours.
I finally solved it by using connect_async parameter when creating the MQTT object instance.
mqtt_client = Mqtt(app, connect_async=True)
With that parameter, the web pages will be displayed and, when the mqtt server is available, it will automatically connect.

Related

ConnectionRefusedError: [Errno 111] Connection refused - MQTT.connect()

I would like some ideas please to catch the error below.
I know what caused the error - I stopped the mosquitto service.
This is a test case because in the real world the broker is on another machine (controlled by HomeAssistant)
In the case of an overall restart / power failure etc there is no guarantee what order devices restart in.
I would like this slave to quietly retry until everything is OK.
I was hoping it could be controlled in the on_connect callback but it never gets that far
it is crashing on the 'G_mqtt_client.connect' call
Traceback (most recent call last):
File "/home/pi/Documents/Code/watering_ctrl_1v00.py", line 382, in <module>
mqtt_initialisation()
File "/home/pi/Documents/Code/watering_ctrl_1v00.py", line 202, in mqtt_initialisation
G_mqtt_client.connect(params.G_broker_url, params.G_broker_port)
File "/home/pi/.local/lib/python3.9/site-packages/paho/mqtt/client.py", line 914, in connect
return self.reconnect()
File "/home/pi/.local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1044, in reconnect
sock = self._create_socket_connection()
File "/home/pi/.local/lib/python3.9/site-packages/paho/mqtt/client.py", line 3685, in _create_socket_connection
return socket.create_connection(addr, timeout=self._connect_timeout, source_address=source)
File "/usr/lib/python3.9/socket.py", line 843, in create_connection
raise err
File "/usr/lib/python3.9/socket.py", line 831, in create_connection
sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused
relevant part of my code
def mqtt_initialisation():
mod = '(messaging.initialisation) '
## establish callback routines - actions to take when events occur
G_mqtt_client.on_connect = on_mqtt_connect
G_mqtt_client.on_disconnect = on_mqtt_disconnect
G_mqtt_client.on_message = message_received
G_mqtt_client.on_log = on_mqtt_log
G_mqtt_client.username_pw_set(params.G_broker_user, params.G_broker_pwd)
G_mqtt_client.connect(params.G_broker_url, params.G_broker_port)
G_mqtt_client.loop_start()
main_log.debug(mod + "after Mqtt client loop start")
def on_mqtt_connect(client, userdata, flags, rc):
main_log.info("MQTT Connected With Result Code " + str(rc)) ## happens at start and if re-connected
do_subscribe()
def on_mqtt_disconnect(client, userdata, rc):
main_log.info("MQTT Client Got Disconnected") ## this appears if, say, mosquitto goes offline
def on_mqtt_log(client, userdata, level, buff):
main_log.info("MQTT Client error ...")
main_log.info(buff)

Error to send e-mail using module smtplib

I'm doing a code to send emails automatically using Python and a local server (where I work). I don't know why this error happens.
I've tried to connect the server using commands from module smtplib -> smtplib.SMTP_SSL(hot, port) and smtplib.SMTP(hot,port) but both doesn't work.
import smtplib
server = smtplib.SMTP('IPfromCompanyServer')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\dbou\AppData\Local\Programs\Python\Python37\lib\smtplib.py", line 251, in __init__
(code, msg) = self.connect(host, port)
File "C:\Users\dbou\AppData\Local\Programs\Python\Python37\lib\smtplib.py", line 336, in connect
self.sock = self._get_socket(host, port, self.timeout)
File "C:\Users\dbou\AppData\Local\Programs\Python\Python37\lib\smtplib.py", line 307, in _get_socket
self.source_address)
File "C:\Users\dbou\AppData\Local\Programs\Python\Python37\lib\socket.py", line 727, in create_connection
raise err
File "C:\Users\dbou\AppData\Local\Programs\Python\Python37\lib\socket.py", line 716, in create_connection
sock.connect(sa)
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
Make sure you're getting to Mail server IP and port number right. And some clients like Gmail don't allow you to send mails automatically without disabling the secure mail transfer feature.
Additionally you could add this piece of code to your program before you log in.
try:
self.smtp.ehlo()
self.smtp.starttls()
self.smtp.ehlo
except:
print "No TLS "
#login here
And maybe this link outta help out a little:
https://superuser.com/questions/1292420/sending-an-email-from-python-using-local-python-smtp-server

How to debug "pika.exceptions.AuthenticationError: EXTERNAL" error when establishing TLS connection to RabbitMQ?

I have a RabbitMQ 3.6.1 server on Ubuntu 14.04 running properly. I tried to configure an SSL listener according to official documentation. No problems during the startup.
However when trying to establish a connection, I get the following error on Python/pika side (full transcript below):
pika.exceptions.AuthenticationError: EXTERNAL
What does EXTERNAL mean here? How to debug / get further details of the error?
Course of actions (to test I used a Vagrant box and a local connection):
RabbitMQ starts SSL Listener on port 5671 (per /var/log/rabbitmq/rabbit#rabbitmq-server.log):
started SSL Listener on [::]:5671
I execute the pika.BlockingConnection on the client side.
On the server side I can see an incoming connection:
=INFO REPORT==== 17-Apr-2016::17:07:15 ===
accepting AMQP connection <0.2788.0> (127.0.0.1:48404 -> 127.0.0.1:5671)
Client fails with:
pika.exceptions.AuthenticationError: EXTERNAL
Server timeouts:
=ERROR REPORT==== 17-Apr-2016::17:07:25 ===
closing AMQP connection <0.2788.0> (127.0.0.1:48404 -> 127.0.0.1:5671):
{handshake_timeout,frame_header}
Full transcript of the client side:
>>> import pika, ssl
>>> from pika.credentials import ExternalCredentials
>>> ssl_options = ({"ca_certs": "/etc/rabbitmq/certs/testca/cacert.pem",
... "certfile": "/etc/rabbitmq/certs/client/cert.pem",
... "keyfile": "/etc/rabbitmq/certs/client/key.pem",
... "cert_reqs": ssl.CERT_REQUIRED,
... "server_side": False})
>>> host = "localhost"
>>> connection = pika.BlockingConnection(
... pika.ConnectionParameters(
... host, 5671, credentials=ExternalCredentials(),
... ssl=True, ssl_options=ssl_options))
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
File "/usr/local/lib/python2.7/dist-packages/pika/adapters/blocking_connection.py", line 339, in __init__
self._process_io_for_connection_setup()
File "/usr/local/lib/python2.7/dist-packages/pika/adapters/blocking_connection.py", line 374, in _process_io_for_connection_setup
self._open_error_result.is_ready)
File "/usr/local/lib/python2.7/dist-packages/pika/adapters/blocking_connection.py", line 410, in _flush_output
self._impl.ioloop.poll()
File "/usr/local/lib/python2.7/dist-packages/pika/adapters/select_connection.py", line 602, in poll
self._process_fd_events(fd_event_map, write_only)
File "/usr/local/lib/python2.7/dist-packages/pika/adapters/select_connection.py", line 443, in _process_fd_events
handler(fileno, events, write_only=write_only)
File "/usr/local/lib/python2.7/dist-packages/pika/adapters/base_connection.py", line 364, in _handle_events
self._handle_read()
File "/usr/local/lib/python2.7/dist-packages/pika/adapters/base_connection.py", line 415, in _handle_read
self._on_data_available(data)
File "/usr/local/lib/python2.7/dist-packages/pika/connection.py", line 1347, in _on_data_available
self._process_frame(frame_value)
File "/usr/local/lib/python2.7/dist-packages/pika/connection.py", line 1414, in _process_frame
if self._process_callbacks(frame_value):
File "/usr/local/lib/python2.7/dist-packages/pika/connection.py", line 1384, in _process_callbacks
frame_value) # Args
File "/usr/local/lib/python2.7/dist-packages/pika/callback.py", line 60, in wrapper
return function(*tuple(args), **kwargs)
File "/usr/local/lib/python2.7/dist-packages/pika/callback.py", line 92, in wrapper
return function(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/pika/callback.py", line 236, in process
callback(*args, **keywords)
File "/usr/local/lib/python2.7/dist-packages/pika/connection.py", line 1298, in _on_connection_start
self._send_connection_start_ok(*self._get_credentials(method_frame))
File "/usr/local/lib/python2.7/dist-packages/pika/connection.py", line 1077, in _get_credentials
raise exceptions.AuthenticationError(self.params.credentials.TYPE)
pika.exceptions.AuthenticationError: EXTERNAL
>>>
The Python / pika code in the question is correct.
The error:
pika.exceptions.AuthenticationError: EXTERNAL
is reported when client certificate authorisation is not enabled on the RabbitMQ server side. The word EXTERNAL in the error refers to the authentication mechanism as described here.
To enable:
rabbitmq-plugins enable rabbitmq_auth_mechanism_ssl

How to catch socket timeout in Python 3?

Part of my script:
def testConnection(self):
# This code doesn't work
try:
self.imap.login(self.user, self.password)
return True
except:
return False
When I try to connect with imaplib to mail server with wrong settings, script always crashes with this error:
Traceback (most recent call last):
File "./mail-notifier.py", line 198, in <module>
mail_check()
File "./mail-notifier.py", line 161, in mail_check
if (SettingsExist() == True and Mail().testConnection() == True):
File "./mail-notifier.py", line 142, in __init__
self.imap = imaplib.IMAP4_SSL(settings.value("MailServer"), settings.value("Port"))
File "/usr/lib64/python3.4/imaplib.py", line 1221, in __init__
IMAP4.__init__(self, host, port)
File "/usr/lib64/python3.4/imaplib.py", line 181, in __init__
self.open(host, port)
File "/usr/lib64/python3.4/imaplib.py", line 1234, in open
IMAP4.open(self, host, port)
File "/usr/lib64/python3.4/imaplib.py", line 257, in open
self.sock = self._create_socket()
File "/usr/lib64/python3.4/imaplib.py", line 1224, in _create_socket
sock = IMAP4._create_socket(self)
File "/usr/lib64/python3.4/imaplib.py", line 247, in _create_socket
return socket.create_connection((self.host, self.port))
File "/usr/lib64/python3.4/socket.py", line 512, in create_connection
raise err
File "/usr/lib64/python3.4/socket.py", line 503, in create_connection
sock.connect(sa)
socket.timeout: timed out
I can't catch timeout exception and print error message and continue to work. I thought " except: " catches all errors that happen. I tried to set " except socket.timeout: " but unsuccessfully. What did I wrong?
socket.connect(address)
Connect to a remote socket at address. (The format of address depends on the address family — see above.)
If the connection is interrupted by a signal, the method waits until the connection completes, or raise a socket.timeout on timeout, if the signal handler doesn’t raise an exception and the socket is blocking or has a timeout. For non-blocking sockets, the method raises an InterruptedError exception if the connection is interrupted by a signal (or the exception raised by the signal handler).
Changed in version 3.5: The method now waits until the connection completes instead of raising an InterruptedError exception if the connection is interrupted by a signal, the signal handler doesn’t raise an exception and the socket is blocking or has a timeout (see the PEP 475 for the rationale).
In case of remote connection you should check if the Internet connection can be established (you and remote destination are reachable) and connection setting to perform actions you want are correct.

Redis example giving HTTP 400: Bad request error

I am trying to cache MySQL queries in my Cherrypy server.
I could not figure out how to solve the error when I was installing pylibmc, so I decided to use Redis-py.
Here I am trying a very simple example.
import redis
cache = redis.StrictRedis(host='localhost', port=8080, db=0)
...
...
cache.set('0', '1') # I also tested with other string keys, but failed with same error
and it's throwing the following error!
[05/May/2014:13:11:13] HTTP Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/cherrypy/_cprequest.py", line 656, in respond
response.body = self.handler()
File "/Library/Python/2.7/site-packages/cherrypy/lib/encoding.py", line 188, in __call__
self.body = self.oldhandler(*args, **kwargs)
File "/Library/Python/2.7/site-packages/cherrypy/_cpdispatch.py", line 34, in __call__
return self.callable(*self.args, **self.kwargs)
File "server.py", line 92, in submit_data
cache.set(str(idx), '1')#res)
File "/Library/Python/2.7/site-packages/redis/client.py", line 897, in set
return self.execute_command('SET', *pieces)
File "/Library/Python/2.7/site-packages/redis/client.py", line 461, in execute_command
return self.parse_response(connection, command_name, **options)
File "/Library/Python/2.7/site-packages/redis/client.py", line 471, in parse_response
response = connection.read_response()
File "/Library/Python/2.7/site-packages/redis/connection.py", line 339, in read_response
response = self._parser.read_response()
File "/Library/Python/2.7/site-packages/redis/connection.py", line 118, in read_response
(str(byte), str(response)))
InvalidResponse: Protocol Error: H, TTP/1.1 400 Bad Request
I could not figure out what was wrong, and my website runs without a problem on localhost at port 8080 when I am not using Redis.
Your webserver is running on port 8080, not your Redis server. Your Redis server is most likely running on port 6379, unless you changed your config for some reason. Right now you are trying to run Redis queries against your webserver, and that is not going to work. Make sure you are connecting to the correct Redis server address and port and then try again.

Categories

Resources