Пример #1
0
    async def sendUDPMessage(self, message):
        """Send the UDP message to the bulb."""
        connid = hex(int(time() * 10000000))[2:]
        data = None
        # overall 10 sec. for time out
        timeout = 10
        send_interval = 0.5
        max_send_datagrams = int(timeout / send_interval)

        try:
            _LOGGER.debug(
                "[wizlight {}, connid {}] connecting to UDP port with send_interval of {} sec.."
                .format(self.ip, connid, send_interval))
            stream = await asyncio.wait_for(
                asyncio_dgram.connect((self.ip, self.port)), timeout)
            _LOGGER.debug(
                "[wizlight {}, connid {}] listening for response datagram".
                format(self.ip, connid))

            receive_task = asyncio.create_task(
                self.receiveUDPwithTimeout(stream, timeout))

            for i in range(max_send_datagrams):
                _LOGGER.debug(
                    "[wizlight {}, connid {}] sending command datagram {}: {}".
                    format(self.ip, connid, i, message))
                asyncio.create_task(stream.send(bytes(message, "utf-8")))
                done, pending = await asyncio.wait([receive_task],
                                                   timeout=send_interval)
                if done:
                    break

            await receive_task
            data = receive_task.result()

        except asyncio.TimeoutError:
            _LOGGER.debug(
                "[wizlight {}, connid {}] Failed to do UDP call(s) to wiz light - Timeout Error!"
                .format(self.ip, connid),
                exc_info=False,
            )
            raise WizLightTimeOutError("The request to the bulb timed out")
        finally:
            try:
                stream.close()
            except UnboundLocalError:
                raise WizLightConnectionError(
                    "Bulb is offline or IP address is not correct.")

        if data is not None and len(data) is not None:
            resp = json.loads(data.decode())
            if "error" not in resp:
                _LOGGER.debug(
                    "[wizlight {}, connid {}] response received: {}".format(
                        self.ip, connid, resp))
                return resp
            else:
                # exception should be created
                raise ValueError("Can't read response from the bulb. Debug:",
                                 resp)
Пример #2
0
 def _check_connection(self):
     """Check the connection to the bulb."""
     message = r'{"method":"getPilot","params":{}}'
     sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
     sock.settimeout(2)
     try:
         # send a udp package
         sock.sendto(bytes(message, "utf-8"), (self.ip, self.port))
         # get the data to
         data, addr = sock.recvfrom(1024)
         if data:
             return
     except socket.timeout:
         raise WizLightTimeOutError(
             "No connection was established by initialization.")
Пример #3
0
 async def send(self, msg_dict: Dict) -> BulbResponse:
     """Serialize a dict to json and send it to device over UDP."""
     self.history.message(HISTORY_SEND, msg_dict)
     message = to_wiz_json(msg_dict)
     await self._ensure_connection()
     assert self.transport is not None
     async with self.lock:
         self.response_method = msg_dict["method"]
         self.response_future = asyncio.Future()
         send_task = asyncio.create_task(
             _send_udp_message_with_retry(message, self.transport,
                                          self.response_future, self.ip,
                                          self.port))
         try:
             resp = await asyncio.wait_for(asyncio.shield(
                 self.response_future),
                                           timeout=TIMEOUT)
         except OSError as ex:
             raise WizLightConnectionError(str(ex)) from ex
         except asyncio.TimeoutError:
             _LOGGER.debug(
                 "%s: Timed out waiting for response to %s after %s tries.",
                 self.ip,
                 message,
                 MAX_SEND_DATAGRAMS,
             )
             raise WizLightTimeOutError("The request to the bulb timed out")
         finally:
             await asyncio.sleep(
                 0)  # Try to let the task finish without cancelation
             if not send_task.done():
                 send_task.cancel()
                 with contextlib.suppress(asyncio.CancelledError):
                     await send_task
     self.history.message(HISTORY_RECIEVE, resp)
     if "error" in resp:
         if resp["error"]["code"] == -32601:
             raise WizLightMethodNotFound(
                 "Method not found; maybe older bulb FW?")
         raise WizLightConnectionError(f'Error recieved: {resp["error"]}')
     return resp