First of all – I’m not even a rookie Python developer. But I wrote an integration that communicates HA with a gateway via UDP protocol. Yet my UDP connector that I wrote is quite… unstable – it lacks reconnections and generally error handling.
Can you point me anywhere where I cant find a good example of how to run UDP socket connection that can communicate two ways?
This is what I wrote, can you point me what can I do better? How can I assure reconnections after gateway restarted or my WiFi connection was lost?
This is a snippet of what I’ve made (I’ve skipped imports):
def setup(hass, config):
gateway = XiaomiGw(hass, config[DOMAIN][CONF_HOST], config[DOMAIN][CONF_PORT])
gateway.create_socket()
gateway.listen_socket()
class XiaomiGw:
def __init__(self, hass, host, port):
self.hass = hass
self._host = host
self._port = port
self._socket = None
self._thread = None
self._listening = False
self._send_queue = Queue(maxsize=25)
def create_socket(self):
_LOGGER.info("Creating socket...")
self._socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
self._socket.settimeout(0.1)
def listen_socket(self):
self._listening = True
self._thread = Thread(target=self._run_socket_thread, args=())
self._thread.daemon = True
self._thread.start()
def send_to_hub(self, data, callback=None):
if callback is not None:
_LOGGER.info("Adding callback for call ID: " + data.id)
self._result_callbacks[data.id] = callback
self._send_queue.put(data)
def _run_socket_thread(self):
_LOGGER.info("Starting listener thread...")
while self._listening:
if self._socket is None:
continue
while not self._send_queue.empty():
data = self._send_queue.get();
_LOGGER.debug("Sending data:")
_LOGGER.debug(data)
self._socket.sendto(data, (self._host, self._port))
try:
data = self._socket.recvfrom(1480)[0]
_LOGGER.debug("Received data:")
_LOGGER.debug(data)
# Gateway available = true
self._set_available()
# Parse all messages in response
self._parse_received_data(data)
except socket.timeout:
pass
Full code can be found here: https://github.com/cadavre/miio_gateway/blob/6e439f490785caf628d521155a0878e5dd28e109/init.py
As you can see it revolves around deamonized Thread with while
loop that uses Socket
to send data (in Queue
) and then try to receive data from socket.
Additionally in background theres a thread that tries to send pings and receive any data that updates state of the component.
I quite feel that using threads with while loops and queues is not the right way to do it. Even if it is – how to “bulletproof” it more?
Thank for any tips or pointing out an examples inside HASS.